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 {
GetElf(art::InstructionSet instruction_set)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