1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <string> 18 #include <llvm/PassManager.h> 19 #include <llvm/Support/TargetRegistry.h> 20 #include <llvm/Support/FormattedStream.h> 21 #include <llvm/Target/TargetMachine.h> 22 #include <llvm/Transforms/IPO.h> 23 #include <llvm/Transforms/IPO/PassManagerBuilder.h> 24 25 #include "base/logging.h" 26 #include "driver/compiler_driver.h" 27 #include "sea_ir/ir/sea.h" 28 #include "sea_ir/code_gen/code_gen.h" 29 30 31 namespace sea_ir { 32 std::string CodeGenData::GetElf(art::InstructionSet instruction_set) { 33 std::string elf; 34 ::llvm::raw_string_ostream out_stream(elf); 35 // Lookup the LLVM target 36 std::string target_triple; 37 std::string target_cpu; 38 std::string target_attr; 39 art::CompilerDriver::InstructionSetToLLVMTarget(instruction_set, 40 target_triple, target_cpu, target_attr); 41 42 std::string errmsg; 43 const ::llvm::Target* target = 44 ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg); 45 46 CHECK(target != NULL) << errmsg; 47 48 // Target options 49 ::llvm::TargetOptions target_options; 50 target_options.FloatABIType = ::llvm::FloatABI::Soft; 51 target_options.NoFramePointerElim = true; 52 target_options.NoFramePointerElimNonLeaf = true; 53 target_options.UseSoftFloat = false; 54 target_options.EnableFastISel = false; 55 56 // Create the ::llvm::TargetMachine 57 ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine( 58 target->createTargetMachine(target_triple, target_cpu, target_attr, target_options, 59 ::llvm::Reloc::Static, ::llvm::CodeModel::Small, 60 ::llvm::CodeGenOpt::Aggressive)); 61 62 CHECK(target_machine.get() != NULL) << "Failed to create target machine"; 63 64 // Add target data 65 const ::llvm::DataLayout* data_layout = target_machine->getDataLayout(); 66 67 // PassManager for code generation passes 68 ::llvm::PassManager pm; 69 pm.add(new ::llvm::DataLayout(*data_layout)); 70 71 // FunctionPassManager for optimization pass 72 ::llvm::FunctionPassManager fpm(&module_); 73 fpm.add(new ::llvm::DataLayout(*data_layout)); 74 75 // Add optimization pass 76 ::llvm::PassManagerBuilder pm_builder; 77 // TODO: Use inliner after we can do IPO. 78 pm_builder.Inliner = NULL; 79 // pm_builder.Inliner = ::llvm::createFunctionInliningPass(); 80 // pm_builder.Inliner = ::llvm::createAlwaysInlinerPass(); 81 // pm_builder.Inliner = ::llvm::createPartialInliningPass(); 82 pm_builder.OptLevel = 3; 83 pm_builder.DisableSimplifyLibCalls = 1; 84 pm_builder.DisableUnitAtATime = 1; 85 pm_builder.populateFunctionPassManager(fpm); 86 pm_builder.populateModulePassManager(pm); 87 pm.add(::llvm::createStripDeadPrototypesPass()); 88 // Add passes to emit ELF image 89 { 90 ::llvm::formatted_raw_ostream formatted_os(out_stream, false); 91 // Ask the target to add backend passes as necessary. 92 if (target_machine->addPassesToEmitFile(pm, 93 formatted_os, 94 ::llvm::TargetMachine::CGFT_ObjectFile, 95 true)) { 96 LOG(FATAL) << "Unable to generate ELF for this target"; 97 } 98 99 // Run the code generation passes 100 pm.run(module_); 101 } 102 return elf; 103 } 104 } // namespace sea_ir 105