blob: a27ea6e41a888d7b673b407ef46c4cf94785b6c0 [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
Logan Chien110bcba2012-04-16 19:11:28 +080019#include "compiled_method.h"
Logan Chien971bf3f2012-05-01 15:47:55 +080020#include "compiler_llvm.h"
Shih-wei Liaod7726e42012-04-20 15:23:36 -070021#include "file.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070022#include "instruction_set.h"
Logan Chien8b977d32012-02-21 19:14:55 +080023#include "ir_builder.h"
24#include "logging.h"
Shih-wei Liaod7726e42012-04-20 15:23:36 -070025#include "os.h"
Logan Chien8b977d32012-02-21 19:14:55 +080026
TDYa127d668a062012-04-13 12:36:57 -070027#include "runtime_support_builder_arm.h"
TDYa127b08ed122012-06-05 23:51:19 -070028#include "runtime_support_builder_thumb2.h"
TDYa127d668a062012-04-13 12:36:57 -070029#include "runtime_support_builder_x86.h"
30
Logan Chien8b977d32012-02-21 19:14:55 +080031#include <llvm/ADT/OwningPtr.h>
32#include <llvm/ADT/StringSet.h>
33#include <llvm/ADT/Triple.h>
34#include <llvm/Analysis/CallGraph.h>
35#include <llvm/Analysis/DebugInfo.h>
TDYa127f15b0ab2012-05-11 21:01:36 -070036#include <llvm/Analysis/Dominators.h>
37#include <llvm/Analysis/LoopInfo.h>
Logan Chien8b977d32012-02-21 19:14:55 +080038#include <llvm/Analysis/LoopPass.h>
39#include <llvm/Analysis/RegionPass.h>
TDYa127f15b0ab2012-05-11 21:01:36 -070040#include <llvm/Analysis/ScalarEvolution.h>
Logan Chien8b977d32012-02-21 19:14:55 +080041#include <llvm/Analysis/Verifier.h>
42#include <llvm/Assembly/PrintModulePass.h>
43#include <llvm/Bitcode/ReaderWriter.h>
44#include <llvm/CallGraphSCCPass.h>
Logan Chien110bcba2012-04-16 19:11:28 +080045#include <llvm/CodeGen/MachineFrameInfo.h>
46#include <llvm/CodeGen/MachineFunction.h>
47#include <llvm/CodeGen/MachineFunctionPass.h>
Logan Chien8b977d32012-02-21 19:14:55 +080048#include <llvm/DerivedTypes.h>
49#include <llvm/LLVMContext.h>
Logan Chien8b977d32012-02-21 19:14:55 +080050#include <llvm/Module.h>
Logan Chien971bf3f2012-05-01 15:47:55 +080051#include <llvm/Object/ObjectFile.h>
Logan Chien8b977d32012-02-21 19:14:55 +080052#include <llvm/PassManager.h>
53#include <llvm/Support/Debug.h>
Logan Chien971bf3f2012-05-01 15:47:55 +080054#include <llvm/Support/ELF.h>
Logan Chien8b977d32012-02-21 19:14:55 +080055#include <llvm/Support/FormattedStream.h>
56#include <llvm/Support/ManagedStatic.h>
Shih-wei Liaod7726e42012-04-20 15:23:36 -070057#include <llvm/Support/MemoryBuffer.h>
Logan Chien8b977d32012-02-21 19:14:55 +080058#include <llvm/Support/PassNameParser.h>
59#include <llvm/Support/PluginLoader.h>
60#include <llvm/Support/PrettyStackTrace.h>
61#include <llvm/Support/Signals.h>
62#include <llvm/Support/SystemUtils.h>
63#include <llvm/Support/TargetRegistry.h>
64#include <llvm/Support/TargetSelect.h>
65#include <llvm/Support/ToolOutputFile.h>
66#include <llvm/Support/raw_ostream.h>
Shih-wei Liaod7726e42012-04-20 15:23:36 -070067#include <llvm/Support/system_error.h>
Logan Chien8b977d32012-02-21 19:14:55 +080068#include <llvm/Target/TargetData.h>
69#include <llvm/Target/TargetLibraryInfo.h>
70#include <llvm/Target/TargetMachine.h>
Shih-wei Liaof1cb9a52012-04-20 01:49:18 -070071#include <llvm/Transforms/IPO.h>
Logan Chien8b977d32012-02-21 19:14:55 +080072#include <llvm/Transforms/IPO/PassManagerBuilder.h>
TDYa127f15b0ab2012-05-11 21:01:36 -070073#include <llvm/Transforms/Scalar.h>
Logan Chien8b977d32012-02-21 19:14:55 +080074
Shih-wei Liaod7726e42012-04-20 15:23:36 -070075#include <sys/types.h>
76#include <sys/wait.h>
77#include <unistd.h>
78
Logan Chien8b977d32012-02-21 19:14:55 +080079#include <string>
80
Logan Chien110bcba2012-04-16 19:11:28 +080081namespace {
82
TDYa127f15b0ab2012-05-11 21:01:36 -070083// TODO: We may need something to manage these passes.
84// TODO: We need high-level IR to analysis and do this at the IRBuilder level.
85class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
86 public:
87 static char ID;
88
89 AddSuspendCheckToLoopLatchPass() : llvm::LoopPass(ID), irb_(NULL) {
90 LOG(FATAL) << "Unexpected instantiation of AddSuspendCheckToLoopLatchPass";
91 // NOTE: We have to declare this constructor for llvm::RegisterPass, but
92 // this constructor won't work because we have no information on
93 // IRBuilder. Thus, we should place a LOG(FATAL) here.
94 }
95
96 AddSuspendCheckToLoopLatchPass(art::compiler_llvm::IRBuilder* irb)
97 : llvm::LoopPass(ID), irb_(irb) {
98 }
99
100 virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
TDYa1279a129452012-07-19 03:10:08 -0700101 AU.addRequired<llvm::LoopInfo>();
TDYa127f15b0ab2012-05-11 21:01:36 -0700102 AU.addRequiredID(llvm::LoopSimplifyID);
103
Shih-wei Liaoba67d7d2012-06-23 18:48:04 -0700104 AU.addPreserved<llvm::DominatorTree>();
TDYa127f15b0ab2012-05-11 21:01:36 -0700105 AU.addPreserved<llvm::LoopInfo>();
Shih-wei Liaoba67d7d2012-06-23 18:48:04 -0700106 AU.addPreservedID(llvm::LoopSimplifyID);
TDYa127f15b0ab2012-05-11 21:01:36 -0700107 AU.addPreserved<llvm::ScalarEvolution>();
108 AU.addPreservedID(llvm::BreakCriticalEdgesID);
109 }
110
111 virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) {
TDYa1279a129452012-07-19 03:10:08 -0700112 llvm::LoopInfo* loop_info = &getAnalysis<llvm::LoopInfo>();
113
TDYa127f15b0ab2012-05-11 21:01:36 -0700114 CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!";
115 llvm::BasicBlock* bb = loop->getLoopLatch();
116 CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist.";
117
TDYa1279a129452012-07-19 03:10:08 -0700118 llvm::BasicBlock* tb = bb->splitBasicBlock(bb->getTerminator(), "suspend_exit");
119 // Remove unconditional branch which is added by splitBasicBlock.
120 bb->getTerminator()->eraseFromParent();
TDYa127f15b0ab2012-05-11 21:01:36 -0700121
TDYa1279a129452012-07-19 03:10:08 -0700122 irb_->SetInsertPoint(bb);
123 irb_->Runtime().EmitTestSuspend();
124 irb_->CreateBr(tb);
125
126 loop->addBasicBlockToLoop(tb, loop_info->getBase());
127 // EmitTestSuspend() creates some basic blocks. We should add them to using
128 // addBasicBlockToLoop(...) as above.
129 for (llvm::succ_iterator succ_iter = llvm::succ_begin(bb), succ_end = llvm::succ_end(bb);
130 succ_iter != succ_end;
131 succ_iter++) {
132 loop->addBasicBlockToLoop(*succ_iter, loop_info->getBase());
133 }
TDYa127f15b0ab2012-05-11 21:01:36 -0700134
135 return true;
136 }
137
138 private:
139 art::compiler_llvm::IRBuilder* irb_;
140};
141
142char AddSuspendCheckToLoopLatchPass::ID = 0;
143
144llvm::RegisterPass<AddSuspendCheckToLoopLatchPass> reg_add_suspend_check_to_loop_latch_pass_(
145 "add-suspend-check-to-loop-latch", "Add suspend check to loop latch pass", false, false);
146
147
Logan Chien110bcba2012-04-16 19:11:28 +0800148} // end anonymous namespace
149
Logan Chien8b977d32012-02-21 19:14:55 +0800150namespace art {
151namespace compiler_llvm {
152
TDYa12755e5e6c2012-09-11 15:14:42 -0700153#if defined(ART_USE_DEXLANG_FRONTEND)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700154llvm::FunctionPass*
155CreateGBCExpanderPass(const greenland::IntrinsicHelper& intrinsic_helper,
156 IRBuilder& irb);
buzbeec531cef2012-10-18 07:09:20 -0700157#elif defined(ART_USE_PORTABLE_COMPILER)
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700158llvm::FunctionPass*
159CreateGBCExpanderPass(const greenland::IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
160 Compiler* compiler, OatCompilationUnit* oat_compilation_unit);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700161#endif
162
Logan Chien8b977d32012-02-21 19:14:55 +0800163llvm::Module* makeLLVMModuleContents(llvm::Module* module);
164
165
Logan Chien971bf3f2012-05-01 15:47:55 +0800166CompilationUnit::CompilationUnit(const CompilerLLVM* compiler_llvm,
167 size_t cunit_idx)
TDYa12755e5e6c2012-09-11 15:14:42 -0700168: compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx) {
buzbeec531cef2012-10-18 07:09:20 -0700169#if !defined(ART_USE_PORTABLE_COMPILER)
TDYa12755e5e6c2012-09-11 15:14:42 -0700170 context_.reset(new llvm::LLVMContext());
Logan Chien8b977d32012-02-21 19:14:55 +0800171 module_ = new llvm::Module("art", *context_);
TDYa12755e5e6c2012-09-11 15:14:42 -0700172#else
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700173 compiler_ = NULL;
174 oat_compilation_unit_ = NULL;
buzbee4df2bbd2012-10-11 14:46:06 -0700175 llvm_info_.reset(new LLVMInfo());
176 context_.reset(llvm_info_->GetLLVMContext());
177 module_ = llvm_info_->GetLLVMModule();
TDYa12755e5e6c2012-09-11 15:14:42 -0700178#endif
179
180 // Include the runtime function declaration
181 makeLLVMModuleContents(module_);
182
183#if defined(ART_USE_DEXLANG_FRONTEND)
184 dex_lang_ctx_ = new greenland::DexLang::Context(*module_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700185#endif
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700186
Logan Chien8b977d32012-02-21 19:14:55 +0800187 // Create IRBuilder
188 irb_.reset(new IRBuilder(*context_, *module_));
TDYa127d668a062012-04-13 12:36:57 -0700189
190 // We always need a switch case, so just use a normal function.
Logan Chien971bf3f2012-05-01 15:47:55 +0800191 switch(GetInstructionSet()) {
TDYa127b08ed122012-06-05 23:51:19 -0700192 default:
193 runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
194 break;
TDYa127d668a062012-04-13 12:36:57 -0700195 case kArm:
TDYa127d668a062012-04-13 12:36:57 -0700196 runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
197 break;
TDYa127b08ed122012-06-05 23:51:19 -0700198 case kThumb2:
199 runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
200 break;
TDYa127d668a062012-04-13 12:36:57 -0700201 case kX86:
202 runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
203 break;
204 }
205
TDYa127d668a062012-04-13 12:36:57 -0700206 irb_->SetRuntimeSupport(runtime_support_.get());
Logan Chien8b977d32012-02-21 19:14:55 +0800207}
208
209
210CompilationUnit::~CompilationUnit() {
TDYa12755e5e6c2012-09-11 15:14:42 -0700211#if defined(ART_USE_DEXLANG_FRONTEND)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700212 delete dex_lang_ctx_;
buzbeec531cef2012-10-18 07:09:20 -0700213#elif defined(ART_USE_PORTABLE_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -0700214 llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_
TDYa12755e5e6c2012-09-11 15:14:42 -0700215 CHECK(llvm_context != NULL);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700216#endif
Logan Chien8b977d32012-02-21 19:14:55 +0800217}
218
219
Logan Chien971bf3f2012-05-01 15:47:55 +0800220InstructionSet CompilationUnit::GetInstructionSet() const {
221 return compiler_llvm_->GetInstructionSet();
Logan Chien8b977d32012-02-21 19:14:55 +0800222}
223
224
Logan Chien971bf3f2012-05-01 15:47:55 +0800225bool CompilationUnit::Materialize() {
226 std::string elf_image;
Logan Chien110bcba2012-04-16 19:11:28 +0800227
Logan Chien971bf3f2012-05-01 15:47:55 +0800228 // Compile and prelink llvm::Module
229 if (!MaterializeToString(elf_image)) {
230 LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_;
Logan Chien971bf3f2012-05-01 15:47:55 +0800231 return false;
Logan Chien110bcba2012-04-16 19:11:28 +0800232 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800233
234#if 0
235 // Dump the ELF image for debugging
236 std::string filename(StringPrintf("%s/Art%zu.elf",
237 GetArtCacheOrDie(GetAndroidData()).c_str(),
238 cunit_idx_));
239 UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
240 output->WriteFully(elf_image.data(), elf_image.size());
241#endif
242
243 // Extract the .text section and prelink the code
244 if (!ExtractCodeAndPrelink(elf_image)) {
245 LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_;
Logan Chien971bf3f2012-05-01 15:47:55 +0800246 return false;
247 }
248
Logan Chien971bf3f2012-05-01 15:47:55 +0800249 return true;
Logan Chien110bcba2012-04-16 19:11:28 +0800250}
251
Logan Chien971bf3f2012-05-01 15:47:55 +0800252
253bool CompilationUnit::MaterializeToString(std::string& str_buffer) {
254 llvm::raw_string_ostream str_os(str_buffer);
255 return MaterializeToRawOStream(str_os);
256}
257
258
259bool CompilationUnit::MaterializeToRawOStream(llvm::raw_ostream& out_stream) {
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700260 // Lookup the LLVM target
Logan Chien12584172012-07-10 04:07:28 -0700261 const char* target_triple = NULL;
262 const char* target_cpu = "";
263 const char* target_attr = NULL;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700264
Logan Chien971bf3f2012-05-01 15:47:55 +0800265 InstructionSet insn_set = GetInstructionSet();
266 switch (insn_set) {
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700267 case kThumb2:
268 target_triple = "thumb-none-linux-gnueabi";
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700269 target_cpu = "cortex-a9";
TDYa127b08ed122012-06-05 23:51:19 -0700270 target_attr = "+thumb2,+neon,+neonfp,+vfp3,+db";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700271 break;
272
273 case kArm:
274 target_triple = "armv7-none-linux-gnueabi";
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700275 // TODO: Fix for Nexus S.
276 target_cpu = "cortex-a9";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700277 // TODO: Fix for Xoom.
TDYa127b08ed122012-06-05 23:51:19 -0700278 target_attr = "+v7,+neon,+neonfp,+vfp3,+db";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700279 break;
280
281 case kX86:
282 target_triple = "i386-pc-linux-gnu";
283 target_attr = "";
284 break;
285
286 case kMips:
287 target_triple = "mipsel-unknown-linux";
288 target_attr = "mips32r2";
289 break;
290
291 default:
Logan Chien971bf3f2012-05-01 15:47:55 +0800292 LOG(FATAL) << "Unknown instruction set: " << insn_set;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700293 }
294
295 std::string errmsg;
Logan Chien12584172012-07-10 04:07:28 -0700296 const llvm::Target* target =
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700297 llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
298
299 CHECK(target != NULL) << errmsg;
300
301 // Target options
302 llvm::TargetOptions target_options;
303 target_options.FloatABIType = llvm::FloatABI::Soft;
304 target_options.NoFramePointerElim = true;
305 target_options.NoFramePointerElimNonLeaf = true;
306 target_options.UseSoftFloat = false;
TDYa1273978da52012-05-19 07:45:39 -0700307 target_options.EnableFastISel = false;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700308
309 // Create the llvm::TargetMachine
Logan Chienb6bed0b2012-05-04 15:03:56 +0800310 llvm::OwningPtr<llvm::TargetMachine> target_machine(
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700311 target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700312 llvm::Reloc::Static, llvm::CodeModel::Small,
Shih-wei Liaodac5eb22012-06-03 14:06:04 -0700313 llvm::CodeGenOpt::Aggressive));
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700314
Logan Chienb6bed0b2012-05-04 15:03:56 +0800315 CHECK(target_machine.get() != NULL) << "Failed to create target machine";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700316
317 // Add target data
Logan Chien12584172012-07-10 04:07:28 -0700318 const llvm::TargetData* target_data = target_machine->getTargetData();
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700319
320 // PassManager for code generation passes
321 llvm::PassManager pm;
322 pm.add(new llvm::TargetData(*target_data));
323
324 // FunctionPassManager for optimization pass
Logan Chien799ef4f2012-04-23 00:17:47 +0800325 llvm::FunctionPassManager fpm(module_);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700326 fpm.add(new llvm::TargetData(*target_data));
327
TDYa127f15b0ab2012-05-11 21:01:36 -0700328 if (bitcode_filename_.empty()) {
329 // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
330 // regular FunctionPass.
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700331#if defined(ART_USE_DEXLANG_FRONTEND)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700332 fpm.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
buzbeec531cef2012-10-18 07:09:20 -0700333#elif defined(ART_USE_PORTABLE_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -0700334 fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700335 compiler_, oat_compilation_unit_));
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700336#endif
TDYa127f15b0ab2012-05-11 21:01:36 -0700337 fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
338 } else {
339 // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file.
340 llvm::FunctionPassManager fpm2(module_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700341#if defined(ART_USE_DEXLANG_FRONTEND)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700342 fpm2.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
buzbeec531cef2012-10-18 07:09:20 -0700343#elif defined(ART_USE_PORTABLE_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -0700344 fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700345 compiler_, oat_compilation_unit_));
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700346#endif
TDYa127f15b0ab2012-05-11 21:01:36 -0700347 fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
348 fpm2.doInitialization();
349 for (llvm::Module::iterator F = module_->begin(), E = module_->end();
350 F != E; ++F) {
351 fpm2.run(*F);
352 }
353 fpm2.doFinalization();
354
355
356 // Write bitcode to file
357 std::string errmsg;
358
359 llvm::OwningPtr<llvm::tool_output_file> out_file(
360 new llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
361 llvm::raw_fd_ostream::F_Binary));
362
363
364 if (!errmsg.empty()) {
365 LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
366 return false;
367 }
368
369 llvm::WriteBitcodeToFile(module_, out_file->os());
370 out_file->keep();
371 }
372
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700373 // Add optimization pass
374 llvm::PassManagerBuilder pm_builder;
TDYa1279a129452012-07-19 03:10:08 -0700375 // TODO: Use inliner after we can do IPO.
376 pm_builder.Inliner = NULL;
Shih-wei Liaoe0e40242012-05-08 01:04:03 -0700377 //pm_builder.Inliner = llvm::createFunctionInliningPass();
TDYa1279a129452012-07-19 03:10:08 -0700378 //pm_builder.Inliner = llvm::createAlwaysInlinerPass();
Shih-wei Liao415576b2012-04-23 15:28:53 -0700379 //pm_builder.Inliner = llvm::createPartialInliningPass();
380 pm_builder.OptLevel = 3;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700381 pm_builder.DisableSimplifyLibCalls = 1;
TDYa127e4c2ccc2012-05-13 21:10:36 -0700382 pm_builder.DisableUnitAtATime = 1;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700383 pm_builder.populateFunctionPassManager(fpm);
TDYa127ce9c3172012-05-15 06:09:27 -0700384 pm_builder.populateModulePassManager(pm);
385 pm.add(llvm::createStripDeadPrototypesPass());
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700386
387 // Add passes to emit ELF image
388 {
Logan Chien08e1ba32012-05-08 15:08:51 +0800389 llvm::formatted_raw_ostream formatted_os(out_stream, false);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700390
391 // Ask the target to add backend passes as necessary.
392 if (target_machine->addPassesToEmitFile(pm,
393 formatted_os,
394 llvm::TargetMachine::CGFT_ObjectFile,
395 true)) {
396 LOG(FATAL) << "Unable to generate ELF for this target";
397 return false;
398 }
399
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700400 // Run the per-function optimization
401 fpm.doInitialization();
Logan Chien799ef4f2012-04-23 00:17:47 +0800402 for (llvm::Module::iterator F = module_->begin(), E = module_->end();
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700403 F != E; ++F) {
404 fpm.run(*F);
405 }
406 fpm.doFinalization();
407
408 // Run the code generation passes
Logan Chien799ef4f2012-04-23 00:17:47 +0800409 pm.run(*module_);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700410 }
411
412 return true;
413}
Logan Chien110bcba2012-04-16 19:11:28 +0800414
Logan Chien971bf3f2012-05-01 15:47:55 +0800415
416bool CompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
Shih-wei Liao02a1e352012-06-30 00:42:07 -0700417 if (GetInstructionSet() == kX86) {
418 compiled_code_.push_back(0xccU);
419 compiled_code_.push_back(0xccU);
420 compiled_code_.push_back(0xccU);
421 compiled_code_.push_back(0xccU);
422 return true;
423 }
424
Logan Chien971bf3f2012-05-01 15:47:55 +0800425 llvm::OwningPtr<llvm::MemoryBuffer> elf_image_buff(
426 llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(elf_image.data(),
427 elf_image.size())));
428
429 llvm::OwningPtr<llvm::object::ObjectFile> elf_file(
430 llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take()));
431
432 llvm::error_code ec;
433
434 const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable();
435
436 for (llvm::object::section_iterator
437 sec_iter = elf_file->begin_sections(),
438 sec_end = elf_file->end_sections();
439 sec_iter != sec_end; sec_iter.increment(ec)) {
440
441 CHECK(ec == 0) << "Failed to read section because " << ec.message();
442
443 // Read the section information
444 llvm::StringRef name;
445 uint64_t alignment = 0u;
446 uint64_t size = 0u;
447
448 CHECK(sec_iter->getName(name) == 0);
449 CHECK(sec_iter->getSize(size) == 0);
450 CHECK(sec_iter->getAlignment(alignment) == 0);
451
452 if (name == ".data" || name == ".bss" || name == ".rodata") {
453 if (size > 0) {
454 LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty "
455 << name.str() << " section";
456 }
457
458 } else if (name == "" || name == ".rel.text" ||
459 name == ".ARM.attributes" || name == ".symtab" ||
460 name == ".strtab" || name == ".shstrtab") {
461 // We can ignore these sections. We don't have to copy them into
462 // the result Oat file.
463
464 } else if (name == ".text") {
465 // Ensure the alignment requirement is less than or equal to
466 // kArchAlignment
467 CheckCodeAlign(alignment);
468
469 // Copy the compiled code
470 llvm::StringRef contents;
471 CHECK(sec_iter->getContents(contents) == 0);
472
473 copy(contents.data(),
474 contents.data() + contents.size(),
475 back_inserter(compiled_code_));
476
477 // Prelink the compiled code
478 for (llvm::object::relocation_iterator
479 rel_iter = sec_iter->begin_relocations(),
480 rel_end = sec_iter->end_relocations(); rel_iter != rel_end;
481 rel_iter.increment(ec)) {
482
483 CHECK(ec == 0) << "Failed to read relocation because " << ec.message();
484
485 // Read the relocation information
486 llvm::object::SymbolRef sym_ref;
487 uint64_t rel_offset = 0;
488 uint64_t rel_type = 0;
489 int64_t rel_addend = 0;
490
491 CHECK(rel_iter->getSymbol(sym_ref) == 0);
492 CHECK(rel_iter->getOffset(rel_offset) == 0);
493 CHECK(rel_iter->getType(rel_type) == 0);
494 CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0);
495
496 // Read the symbol related to this relocation fixup
497 llvm::StringRef sym_name;
498 CHECK(sym_ref.getName(sym_name) == 0);
499
500 // Relocate the fixup.
501 // TODO: Support more relocation type.
502 CHECK(rel_type == llvm::ELF::R_ARM_ABS32);
503 CHECK_LE(rel_offset + 4, compiled_code_.size());
504
505 uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str());
506 uintptr_t final_addr = dest_addr + rel_addend;
507 compiled_code_[rel_offset] = final_addr & 0xff;
508 compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff;
509 compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff;
510 compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff;
511 }
512
513 } else {
514 LOG(WARNING) << "Unexpected section: " << name.str();
515 }
516 }
517
518 return true;
519}
520
521
522// Check whether the align is less than or equal to the code alignment of
523// that architecture. Since the Oat writer only guarantee that the compiled
524// method being aligned to kArchAlignment, we have no way to align the ELf
525// section if the section alignment is greater than kArchAlignment.
526void CompilationUnit::CheckCodeAlign(uint32_t align) const {
527 InstructionSet insn_set = GetInstructionSet();
528 switch (insn_set) {
529 case kThumb2:
530 case kArm:
531 CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
532 break;
533
534 case kX86:
535 CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
536 break;
537
538 case kMips:
539 CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
540 break;
541
542 default:
543 LOG(FATAL) << "Unknown instruction set: " << insn_set;
544 }
545}
546
547
Logan Chien8b977d32012-02-21 19:14:55 +0800548} // namespace compiler_llvm
549} // namespace art