blob: fde023c914ba7005577d2f1dff45b057ea698d1e [file] [log] [blame]
Logan Chien8b977d32012-02-21 19:14:55 +08001/*
2 * Copyright (C) 2012 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 "compilation_unit.h"
18
Elliott Hughes0f3c5532012-03-30 14:51:51 -070019#include "instruction_set.h"
Logan Chien8b977d32012-02-21 19:14:55 +080020#include "ir_builder.h"
21#include "logging.h"
22
TDYa127d668a062012-04-13 12:36:57 -070023#include "runtime_support_builder_arm.h"
24#include "runtime_support_builder_x86.h"
25
Logan Chien8b977d32012-02-21 19:14:55 +080026#include <llvm/ADT/OwningPtr.h>
27#include <llvm/ADT/StringSet.h>
28#include <llvm/ADT/Triple.h>
29#include <llvm/Analysis/CallGraph.h>
30#include <llvm/Analysis/DebugInfo.h>
31#include <llvm/Analysis/LoopPass.h>
32#include <llvm/Analysis/RegionPass.h>
33#include <llvm/Analysis/Verifier.h>
34#include <llvm/Assembly/PrintModulePass.h>
35#include <llvm/Bitcode/ReaderWriter.h>
36#include <llvm/CallGraphSCCPass.h>
37#include <llvm/DerivedTypes.h>
38#include <llvm/LLVMContext.h>
Logan Chien8b977d32012-02-21 19:14:55 +080039#include <llvm/Module.h>
40#include <llvm/PassManager.h>
41#include <llvm/Support/Debug.h>
42#include <llvm/Support/FormattedStream.h>
43#include <llvm/Support/ManagedStatic.h>
44#include <llvm/Support/PassNameParser.h>
45#include <llvm/Support/PluginLoader.h>
46#include <llvm/Support/PrettyStackTrace.h>
47#include <llvm/Support/Signals.h>
48#include <llvm/Support/SystemUtils.h>
49#include <llvm/Support/TargetRegistry.h>
50#include <llvm/Support/TargetSelect.h>
51#include <llvm/Support/ToolOutputFile.h>
52#include <llvm/Support/raw_ostream.h>
53#include <llvm/Target/TargetData.h>
54#include <llvm/Target/TargetLibraryInfo.h>
55#include <llvm/Target/TargetMachine.h>
56#include <llvm/Transforms/IPO/PassManagerBuilder.h>
57
58#include <string>
59
60namespace art {
61namespace compiler_llvm {
62
63llvm::Module* makeLLVMModuleContents(llvm::Module* module);
64
65
Logan Chien6546ec52012-03-17 20:08:29 +080066CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx)
67: insn_set_(insn_set), elf_idx_(elf_idx), context_(new llvm::LLVMContext()),
Logan Chien937105a2012-04-02 02:37:37 +080068 mem_usage_(0), num_elf_funcs_(0) {
Logan Chien8b977d32012-02-21 19:14:55 +080069
70 // Create the module and include the runtime function declaration
71 module_ = new llvm::Module("art", *context_);
72 makeLLVMModuleContents(module_);
73
74 // Create IRBuilder
75 irb_.reset(new IRBuilder(*context_, *module_));
TDYa127d668a062012-04-13 12:36:57 -070076
77 // We always need a switch case, so just use a normal function.
78 switch(insn_set_) {
79 default:
80 runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
81 break;
82 case kArm:
83 case kThumb2:
84 runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
85 break;
86 case kX86:
87 runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
88 break;
89 }
90
91 runtime_support_->OptimizeRuntimeSupport();
92
93 irb_->SetRuntimeSupport(runtime_support_.get());
Logan Chien8b977d32012-02-21 19:14:55 +080094}
95
96
97CompilationUnit::~CompilationUnit() {
98}
99
100
101bool CompilationUnit::WriteBitcodeToFile() {
102 std::string errmsg;
103
104 llvm::OwningPtr<llvm::tool_output_file> out_file(
105 new llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
106 llvm::raw_fd_ostream::F_Binary));
107
108
109 if (!errmsg.empty()) {
110 LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
111 return false;
112 }
113
114 llvm::WriteBitcodeToFile(module_, out_file->os());
115 out_file->keep();
116
117 return true;
118}
119
120
121bool CompilationUnit::Materialize() {
Logan Chien8b977d32012-02-21 19:14:55 +0800122 // Lookup the LLVM target
123 char const* target_triple = NULL;
124 char const* target_attr = NULL;
125
Logan Chien8ee03b52012-03-01 13:53:02 +0800126 switch (insn_set_) {
127 case kThumb2:
Logan Chien8b977d32012-02-21 19:14:55 +0800128 target_triple = "thumb-none-linux-gnueabi";
129 target_attr = "+thumb2,+neon,+neonfp,+vfp3";
Logan Chien8ee03b52012-03-01 13:53:02 +0800130 break;
131
132 case kArm:
Logan Chien8b977d32012-02-21 19:14:55 +0800133 target_triple = "armv7-none-linux-gnueabi";
134 target_attr = "+v7,+neon,+neonfp,+vfp3";
Logan Chien8ee03b52012-03-01 13:53:02 +0800135 break;
136
137 case kX86:
Logan Chien8b977d32012-02-21 19:14:55 +0800138 target_triple = "i386-pc-linux-gnu";
139 target_attr = "";
Logan Chien8ee03b52012-03-01 13:53:02 +0800140 break;
141
Shih-wei Liao6edfde42012-03-01 15:49:12 -0800142 case kMips:
143 target_triple = "mipsel-unknown-linux";
144 target_attr = "mips32r2";
145 break;
Logan Chien8ee03b52012-03-01 13:53:02 +0800146
147 default:
Logan Chien8b977d32012-02-21 19:14:55 +0800148 LOG(FATAL) << "Unknown instruction set: " << insn_set_;
149 }
150
151 std::string errmsg;
152 llvm::Target const* target =
153 llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
154
155 CHECK(target != NULL) << errmsg;
156
157 // Target options
158 llvm::TargetOptions target_options;
Logan Chien8b977d32012-02-21 19:14:55 +0800159 target_options.FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -0800160 target_options.NoFramePointerElim = true;
161 target_options.NoFramePointerElimNonLeaf = true;
Logan Chien6d6d7542012-03-02 14:00:31 +0800162 target_options.UseSoftFloat = false;
Shih-wei Liaoc6c317e2012-03-30 01:41:18 -0700163 target_options.EnableFastISel = true;
Logan Chien8b977d32012-02-21 19:14:55 +0800164
165 // Create the llvm::TargetMachine
166 llvm::TargetMachine* target_machine =
167 target->createTargetMachine(target_triple, "", target_attr, target_options,
168 llvm::Reloc::Static, llvm::CodeModel::Small,
169 llvm::CodeGenOpt::Aggressive);
170
171 CHECK(target_machine != NULL) << "Failed to create target machine";
172
173
174 // Add target data
175 llvm::TargetData const* target_data = target_machine->getTargetData();
176
177 // PassManager for code generation passes
178 llvm::PassManager pm;
179 pm.add(new llvm::TargetData(*target_data));
180
181 // FunctionPassManager for optimization pass
182 llvm::FunctionPassManager fpm(module_);
183 fpm.add(new llvm::TargetData(*target_data));
184
185 // Add optimization pass
186 llvm::PassManagerBuilder pm_builder;
187 pm_builder.Inliner = NULL; // TODO: add some inline in the future
188 pm_builder.OptLevel = 3;
189 pm_builder.DisableSimplifyLibCalls = 1;
190 pm_builder.populateModulePassManager(pm);
191 pm_builder.populateFunctionPassManager(fpm);
192
Logan Chienb9eaeea2012-03-17 19:45:01 +0800193 // Add passes to emit ELF image
194 {
195 llvm::formatted_raw_ostream formatted_os(
196 *(new llvm::raw_string_ostream(elf_image_)), true);
197
198 // Ask the target to add backend passes as necessary.
199 if (target_machine->addPassesToEmitFile(pm,
200 formatted_os,
201 llvm::TargetMachine::CGFT_ObjectFile,
202 true)) {
203 LOG(FATAL) << "Unable to generate ELF for this target";
204 return false;
205 }
206
207 // Run the per-function optimization
208 fpm.doInitialization();
209 for (llvm::Module::iterator F = module_->begin(), E = module_->end();
210 F != E; ++F) {
211 fpm.run(*F);
212 }
213 fpm.doFinalization();
214
215 // Run the code generation passes
216 pm.run(*module_);
217 }
218
Logan Chiende08e842012-03-21 00:34:12 +0800219 LOG(INFO) << "Compilation Unit: " << elf_idx_ << " (done)";
Logan Chien7f767612012-03-01 18:54:49 +0800220
221 // Free the resources
222 context_.reset(NULL);
223 irb_.reset(NULL);
224 module_ = NULL;
Logan Chien8b977d32012-02-21 19:14:55 +0800225
226 return true;
227}
228
229
Logan Chien8b977d32012-02-21 19:14:55 +0800230} // namespace compiler_llvm
231} // namespace art