blob: 596169b38cb7b71312ffdc40e9735fd2fe580b1a [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 Hughes07ed66b2012-12-12 18:34:25 -080019#include "base/logging.h"
Logan Chien110bcba2012-04-16 19:11:28 +080020#include "compiled_method.h"
Logan Chien971bf3f2012-05-01 15:47:55 +080021#include "compiler_llvm.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"
Shih-wei Liaod7726e42012-04-20 15:23:36 -070024#include "os.h"
Logan Chien8b977d32012-02-21 19:14:55 +080025
TDYa127d668a062012-04-13 12:36:57 -070026#include "runtime_support_builder_arm.h"
TDYa127b08ed122012-06-05 23:51:19 -070027#include "runtime_support_builder_thumb2.h"
TDYa127d668a062012-04-13 12:36:57 -070028#include "runtime_support_builder_x86.h"
29
Logan Chien8b977d32012-02-21 19:14:55 +080030#include <llvm/ADT/OwningPtr.h>
31#include <llvm/ADT/StringSet.h>
32#include <llvm/ADT/Triple.h>
33#include <llvm/Analysis/CallGraph.h>
34#include <llvm/Analysis/DebugInfo.h>
TDYa127f15b0ab2012-05-11 21:01:36 -070035#include <llvm/Analysis/Dominators.h>
36#include <llvm/Analysis/LoopInfo.h>
Logan Chien8b977d32012-02-21 19:14:55 +080037#include <llvm/Analysis/LoopPass.h>
38#include <llvm/Analysis/RegionPass.h>
TDYa127f15b0ab2012-05-11 21:01:36 -070039#include <llvm/Analysis/ScalarEvolution.h>
Logan Chien8b977d32012-02-21 19:14:55 +080040#include <llvm/Analysis/Verifier.h>
41#include <llvm/Assembly/PrintModulePass.h>
42#include <llvm/Bitcode/ReaderWriter.h>
43#include <llvm/CallGraphSCCPass.h>
Logan Chien110bcba2012-04-16 19:11:28 +080044#include <llvm/CodeGen/MachineFrameInfo.h>
45#include <llvm/CodeGen/MachineFunction.h>
46#include <llvm/CodeGen/MachineFunctionPass.h>
Logan Chien8b977d32012-02-21 19:14:55 +080047#include <llvm/DerivedTypes.h>
48#include <llvm/LLVMContext.h>
Logan Chien8b977d32012-02-21 19:14:55 +080049#include <llvm/Module.h>
Logan Chien971bf3f2012-05-01 15:47:55 +080050#include <llvm/Object/ObjectFile.h>
Logan Chien8b977d32012-02-21 19:14:55 +080051#include <llvm/PassManager.h>
52#include <llvm/Support/Debug.h>
Logan Chien971bf3f2012-05-01 15:47:55 +080053#include <llvm/Support/ELF.h>
Logan Chien8b977d32012-02-21 19:14:55 +080054#include <llvm/Support/FormattedStream.h>
55#include <llvm/Support/ManagedStatic.h>
Shih-wei Liaod7726e42012-04-20 15:23:36 -070056#include <llvm/Support/MemoryBuffer.h>
Logan Chien8b977d32012-02-21 19:14:55 +080057#include <llvm/Support/PassNameParser.h>
58#include <llvm/Support/PluginLoader.h>
59#include <llvm/Support/PrettyStackTrace.h>
60#include <llvm/Support/Signals.h>
61#include <llvm/Support/SystemUtils.h>
62#include <llvm/Support/TargetRegistry.h>
63#include <llvm/Support/TargetSelect.h>
64#include <llvm/Support/ToolOutputFile.h>
65#include <llvm/Support/raw_ostream.h>
Shih-wei Liaod7726e42012-04-20 15:23:36 -070066#include <llvm/Support/system_error.h>
Logan Chien8b977d32012-02-21 19:14:55 +080067#include <llvm/Target/TargetData.h>
68#include <llvm/Target/TargetLibraryInfo.h>
69#include <llvm/Target/TargetMachine.h>
Shih-wei Liaof1cb9a52012-04-20 01:49:18 -070070#include <llvm/Transforms/IPO.h>
Logan Chien8b977d32012-02-21 19:14:55 +080071#include <llvm/Transforms/IPO/PassManagerBuilder.h>
TDYa127f15b0ab2012-05-11 21:01:36 -070072#include <llvm/Transforms/Scalar.h>
Logan Chien8b977d32012-02-21 19:14:55 +080073
Shih-wei Liaod7726e42012-04-20 15:23:36 -070074#include <sys/types.h>
75#include <sys/wait.h>
76#include <unistd.h>
77
Logan Chien8b977d32012-02-21 19:14:55 +080078#include <string>
79
80namespace art {
81namespace compiler_llvm {
82
TDYa12755e5e6c2012-09-11 15:14:42 -070083#if defined(ART_USE_DEXLANG_FRONTEND)
Shih-wei Liao21d28f52012-06-12 05:55:00 -070084llvm::FunctionPass*
85CreateGBCExpanderPass(const greenland::IntrinsicHelper& intrinsic_helper,
86 IRBuilder& irb);
buzbeec531cef2012-10-18 07:09:20 -070087#elif defined(ART_USE_PORTABLE_COMPILER)
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -070088llvm::FunctionPass*
89CreateGBCExpanderPass(const greenland::IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
90 Compiler* compiler, OatCompilationUnit* oat_compilation_unit);
Shih-wei Liao21d28f52012-06-12 05:55:00 -070091#endif
92
Logan Chien8b977d32012-02-21 19:14:55 +080093llvm::Module* makeLLVMModuleContents(llvm::Module* module);
94
95
Logan Chien971bf3f2012-05-01 15:47:55 +080096CompilationUnit::CompilationUnit(const CompilerLLVM* compiler_llvm,
97 size_t cunit_idx)
TDYa12755e5e6c2012-09-11 15:14:42 -070098: compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx) {
buzbeec531cef2012-10-18 07:09:20 -070099#if !defined(ART_USE_PORTABLE_COMPILER)
TDYa12755e5e6c2012-09-11 15:14:42 -0700100 context_.reset(new llvm::LLVMContext());
Logan Chien8b977d32012-02-21 19:14:55 +0800101 module_ = new llvm::Module("art", *context_);
TDYa12755e5e6c2012-09-11 15:14:42 -0700102#else
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700103 compiler_ = NULL;
104 oat_compilation_unit_ = NULL;
buzbee4df2bbd2012-10-11 14:46:06 -0700105 llvm_info_.reset(new LLVMInfo());
106 context_.reset(llvm_info_->GetLLVMContext());
107 module_ = llvm_info_->GetLLVMModule();
TDYa12755e5e6c2012-09-11 15:14:42 -0700108#endif
109
110 // Include the runtime function declaration
111 makeLLVMModuleContents(module_);
112
113#if defined(ART_USE_DEXLANG_FRONTEND)
114 dex_lang_ctx_ = new greenland::DexLang::Context(*module_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700115#endif
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700116
Logan Chien8b977d32012-02-21 19:14:55 +0800117 // Create IRBuilder
118 irb_.reset(new IRBuilder(*context_, *module_));
TDYa127d668a062012-04-13 12:36:57 -0700119
120 // We always need a switch case, so just use a normal function.
Logan Chien971bf3f2012-05-01 15:47:55 +0800121 switch(GetInstructionSet()) {
TDYa127b08ed122012-06-05 23:51:19 -0700122 default:
123 runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
124 break;
TDYa127d668a062012-04-13 12:36:57 -0700125 case kArm:
TDYa127d668a062012-04-13 12:36:57 -0700126 runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
127 break;
TDYa127b08ed122012-06-05 23:51:19 -0700128 case kThumb2:
129 runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
130 break;
TDYa127d668a062012-04-13 12:36:57 -0700131 case kX86:
132 runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
133 break;
134 }
135
TDYa127d668a062012-04-13 12:36:57 -0700136 irb_->SetRuntimeSupport(runtime_support_.get());
Logan Chien8b977d32012-02-21 19:14:55 +0800137}
138
139
140CompilationUnit::~CompilationUnit() {
TDYa12755e5e6c2012-09-11 15:14:42 -0700141#if defined(ART_USE_DEXLANG_FRONTEND)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700142 delete dex_lang_ctx_;
buzbeec531cef2012-10-18 07:09:20 -0700143#elif defined(ART_USE_PORTABLE_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -0700144 llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_
TDYa12755e5e6c2012-09-11 15:14:42 -0700145 CHECK(llvm_context != NULL);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700146#endif
Logan Chien8b977d32012-02-21 19:14:55 +0800147}
148
149
Logan Chien971bf3f2012-05-01 15:47:55 +0800150InstructionSet CompilationUnit::GetInstructionSet() const {
151 return compiler_llvm_->GetInstructionSet();
Logan Chien8b977d32012-02-21 19:14:55 +0800152}
153
154
Logan Chien971bf3f2012-05-01 15:47:55 +0800155bool CompilationUnit::Materialize() {
156 std::string elf_image;
Logan Chien110bcba2012-04-16 19:11:28 +0800157
Logan Chien971bf3f2012-05-01 15:47:55 +0800158 // Compile and prelink llvm::Module
159 if (!MaterializeToString(elf_image)) {
160 LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_;
Logan Chien971bf3f2012-05-01 15:47:55 +0800161 return false;
Logan Chien110bcba2012-04-16 19:11:28 +0800162 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800163
164#if 0
165 // Dump the ELF image for debugging
166 std::string filename(StringPrintf("%s/Art%zu.elf",
167 GetArtCacheOrDie(GetAndroidData()).c_str(),
168 cunit_idx_));
169 UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
170 output->WriteFully(elf_image.data(), elf_image.size());
171#endif
172
173 // Extract the .text section and prelink the code
174 if (!ExtractCodeAndPrelink(elf_image)) {
175 LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_;
Logan Chien971bf3f2012-05-01 15:47:55 +0800176 return false;
177 }
178
Logan Chien971bf3f2012-05-01 15:47:55 +0800179 return true;
Logan Chien110bcba2012-04-16 19:11:28 +0800180}
181
Logan Chien971bf3f2012-05-01 15:47:55 +0800182
183bool CompilationUnit::MaterializeToString(std::string& str_buffer) {
184 llvm::raw_string_ostream str_os(str_buffer);
185 return MaterializeToRawOStream(str_os);
186}
187
188
189bool CompilationUnit::MaterializeToRawOStream(llvm::raw_ostream& out_stream) {
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700190 // Lookup the LLVM target
Logan Chien12584172012-07-10 04:07:28 -0700191 const char* target_triple = NULL;
192 const char* target_cpu = "";
193 const char* target_attr = NULL;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700194
Logan Chien971bf3f2012-05-01 15:47:55 +0800195 InstructionSet insn_set = GetInstructionSet();
196 switch (insn_set) {
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700197 case kThumb2:
198 target_triple = "thumb-none-linux-gnueabi";
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700199 target_cpu = "cortex-a9";
TDYa127b08ed122012-06-05 23:51:19 -0700200 target_attr = "+thumb2,+neon,+neonfp,+vfp3,+db";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700201 break;
202
203 case kArm:
204 target_triple = "armv7-none-linux-gnueabi";
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700205 // TODO: Fix for Nexus S.
206 target_cpu = "cortex-a9";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700207 // TODO: Fix for Xoom.
TDYa127b08ed122012-06-05 23:51:19 -0700208 target_attr = "+v7,+neon,+neonfp,+vfp3,+db";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700209 break;
210
211 case kX86:
212 target_triple = "i386-pc-linux-gnu";
213 target_attr = "";
214 break;
215
216 case kMips:
217 target_triple = "mipsel-unknown-linux";
218 target_attr = "mips32r2";
219 break;
220
221 default:
Logan Chien971bf3f2012-05-01 15:47:55 +0800222 LOG(FATAL) << "Unknown instruction set: " << insn_set;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700223 }
224
225 std::string errmsg;
Logan Chien12584172012-07-10 04:07:28 -0700226 const llvm::Target* target =
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700227 llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
228
229 CHECK(target != NULL) << errmsg;
230
231 // Target options
232 llvm::TargetOptions target_options;
233 target_options.FloatABIType = llvm::FloatABI::Soft;
234 target_options.NoFramePointerElim = true;
235 target_options.NoFramePointerElimNonLeaf = true;
236 target_options.UseSoftFloat = false;
TDYa1273978da52012-05-19 07:45:39 -0700237 target_options.EnableFastISel = false;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700238
239 // Create the llvm::TargetMachine
Logan Chienb6bed0b2012-05-04 15:03:56 +0800240 llvm::OwningPtr<llvm::TargetMachine> target_machine(
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700241 target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700242 llvm::Reloc::Static, llvm::CodeModel::Small,
Shih-wei Liaodac5eb22012-06-03 14:06:04 -0700243 llvm::CodeGenOpt::Aggressive));
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700244
Logan Chienb6bed0b2012-05-04 15:03:56 +0800245 CHECK(target_machine.get() != NULL) << "Failed to create target machine";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700246
247 // Add target data
Logan Chien12584172012-07-10 04:07:28 -0700248 const llvm::TargetData* target_data = target_machine->getTargetData();
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700249
250 // PassManager for code generation passes
251 llvm::PassManager pm;
252 pm.add(new llvm::TargetData(*target_data));
253
254 // FunctionPassManager for optimization pass
Logan Chien799ef4f2012-04-23 00:17:47 +0800255 llvm::FunctionPassManager fpm(module_);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700256 fpm.add(new llvm::TargetData(*target_data));
257
TDYa127f15b0ab2012-05-11 21:01:36 -0700258 if (bitcode_filename_.empty()) {
259 // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
260 // regular FunctionPass.
TDYa127ce4cc0d2012-11-18 16:59:53 -0800261#if defined(ART_USE_PORTABLE_COMPILER)
buzbee4df2bbd2012-10-11 14:46:06 -0700262 fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700263 compiler_, oat_compilation_unit_));
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700264#endif
TDYa127f15b0ab2012-05-11 21:01:36 -0700265 } else {
TDYa127ce4cc0d2012-11-18 16:59:53 -0800266#if defined(ART_USE_PORTABLE_COMPILER)
TDYa127f15b0ab2012-05-11 21:01:36 -0700267 llvm::FunctionPassManager fpm2(module_);
buzbee4df2bbd2012-10-11 14:46:06 -0700268 fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700269 compiler_, oat_compilation_unit_));
TDYa127f15b0ab2012-05-11 21:01:36 -0700270 fpm2.doInitialization();
271 for (llvm::Module::iterator F = module_->begin(), E = module_->end();
272 F != E; ++F) {
273 fpm2.run(*F);
274 }
275 fpm2.doFinalization();
TDYa127ce4cc0d2012-11-18 16:59:53 -0800276#endif
TDYa127f15b0ab2012-05-11 21:01:36 -0700277
278 // Write bitcode to file
279 std::string errmsg;
280
281 llvm::OwningPtr<llvm::tool_output_file> out_file(
282 new llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
283 llvm::raw_fd_ostream::F_Binary));
284
285
286 if (!errmsg.empty()) {
287 LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
288 return false;
289 }
290
291 llvm::WriteBitcodeToFile(module_, out_file->os());
292 out_file->keep();
293 }
294
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700295 // Add optimization pass
296 llvm::PassManagerBuilder pm_builder;
TDYa1279a129452012-07-19 03:10:08 -0700297 // TODO: Use inliner after we can do IPO.
298 pm_builder.Inliner = NULL;
Shih-wei Liaoe0e40242012-05-08 01:04:03 -0700299 //pm_builder.Inliner = llvm::createFunctionInliningPass();
TDYa1279a129452012-07-19 03:10:08 -0700300 //pm_builder.Inliner = llvm::createAlwaysInlinerPass();
Shih-wei Liao415576b2012-04-23 15:28:53 -0700301 //pm_builder.Inliner = llvm::createPartialInliningPass();
302 pm_builder.OptLevel = 3;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700303 pm_builder.DisableSimplifyLibCalls = 1;
TDYa127e4c2ccc2012-05-13 21:10:36 -0700304 pm_builder.DisableUnitAtATime = 1;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700305 pm_builder.populateFunctionPassManager(fpm);
TDYa127ce9c3172012-05-15 06:09:27 -0700306 pm_builder.populateModulePassManager(pm);
307 pm.add(llvm::createStripDeadPrototypesPass());
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700308
309 // Add passes to emit ELF image
310 {
Logan Chien08e1ba32012-05-08 15:08:51 +0800311 llvm::formatted_raw_ostream formatted_os(out_stream, false);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700312
313 // Ask the target to add backend passes as necessary.
314 if (target_machine->addPassesToEmitFile(pm,
315 formatted_os,
316 llvm::TargetMachine::CGFT_ObjectFile,
317 true)) {
318 LOG(FATAL) << "Unable to generate ELF for this target";
319 return false;
320 }
321
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700322 // Run the per-function optimization
323 fpm.doInitialization();
Logan Chien799ef4f2012-04-23 00:17:47 +0800324 for (llvm::Module::iterator F = module_->begin(), E = module_->end();
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700325 F != E; ++F) {
326 fpm.run(*F);
327 }
328 fpm.doFinalization();
329
330 // Run the code generation passes
Logan Chien799ef4f2012-04-23 00:17:47 +0800331 pm.run(*module_);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700332 }
333
334 return true;
335}
Logan Chien110bcba2012-04-16 19:11:28 +0800336
Logan Chien971bf3f2012-05-01 15:47:55 +0800337
338bool CompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
Shih-wei Liao02a1e352012-06-30 00:42:07 -0700339 if (GetInstructionSet() == kX86) {
340 compiled_code_.push_back(0xccU);
341 compiled_code_.push_back(0xccU);
342 compiled_code_.push_back(0xccU);
343 compiled_code_.push_back(0xccU);
344 return true;
345 }
346
Logan Chien971bf3f2012-05-01 15:47:55 +0800347 llvm::OwningPtr<llvm::MemoryBuffer> elf_image_buff(
348 llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(elf_image.data(),
349 elf_image.size())));
350
351 llvm::OwningPtr<llvm::object::ObjectFile> elf_file(
352 llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take()));
353
354 llvm::error_code ec;
355
356 const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable();
357
358 for (llvm::object::section_iterator
359 sec_iter = elf_file->begin_sections(),
360 sec_end = elf_file->end_sections();
361 sec_iter != sec_end; sec_iter.increment(ec)) {
362
363 CHECK(ec == 0) << "Failed to read section because " << ec.message();
364
365 // Read the section information
366 llvm::StringRef name;
367 uint64_t alignment = 0u;
368 uint64_t size = 0u;
369
370 CHECK(sec_iter->getName(name) == 0);
371 CHECK(sec_iter->getSize(size) == 0);
372 CHECK(sec_iter->getAlignment(alignment) == 0);
373
374 if (name == ".data" || name == ".bss" || name == ".rodata") {
375 if (size > 0) {
376 LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty "
377 << name.str() << " section";
378 }
379
380 } else if (name == "" || name == ".rel.text" ||
381 name == ".ARM.attributes" || name == ".symtab" ||
382 name == ".strtab" || name == ".shstrtab") {
383 // We can ignore these sections. We don't have to copy them into
384 // the result Oat file.
385
386 } else if (name == ".text") {
387 // Ensure the alignment requirement is less than or equal to
388 // kArchAlignment
389 CheckCodeAlign(alignment);
390
391 // Copy the compiled code
392 llvm::StringRef contents;
393 CHECK(sec_iter->getContents(contents) == 0);
394
395 copy(contents.data(),
396 contents.data() + contents.size(),
397 back_inserter(compiled_code_));
398
399 // Prelink the compiled code
400 for (llvm::object::relocation_iterator
401 rel_iter = sec_iter->begin_relocations(),
402 rel_end = sec_iter->end_relocations(); rel_iter != rel_end;
403 rel_iter.increment(ec)) {
404
405 CHECK(ec == 0) << "Failed to read relocation because " << ec.message();
406
407 // Read the relocation information
408 llvm::object::SymbolRef sym_ref;
409 uint64_t rel_offset = 0;
410 uint64_t rel_type = 0;
411 int64_t rel_addend = 0;
412
413 CHECK(rel_iter->getSymbol(sym_ref) == 0);
414 CHECK(rel_iter->getOffset(rel_offset) == 0);
415 CHECK(rel_iter->getType(rel_type) == 0);
416 CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0);
417
418 // Read the symbol related to this relocation fixup
419 llvm::StringRef sym_name;
420 CHECK(sym_ref.getName(sym_name) == 0);
421
422 // Relocate the fixup.
423 // TODO: Support more relocation type.
424 CHECK(rel_type == llvm::ELF::R_ARM_ABS32);
425 CHECK_LE(rel_offset + 4, compiled_code_.size());
426
427 uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str());
428 uintptr_t final_addr = dest_addr + rel_addend;
429 compiled_code_[rel_offset] = final_addr & 0xff;
430 compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff;
431 compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff;
432 compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff;
433 }
434
435 } else {
436 LOG(WARNING) << "Unexpected section: " << name.str();
437 }
438 }
439
440 return true;
441}
442
443
444// Check whether the align is less than or equal to the code alignment of
445// that architecture. Since the Oat writer only guarantee that the compiled
446// method being aligned to kArchAlignment, we have no way to align the ELf
447// section if the section alignment is greater than kArchAlignment.
448void CompilationUnit::CheckCodeAlign(uint32_t align) const {
449 InstructionSet insn_set = GetInstructionSet();
450 switch (insn_set) {
451 case kThumb2:
452 case kArm:
453 CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
454 break;
455
456 case kX86:
457 CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
458 break;
459
460 case kMips:
461 CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
462 break;
463
464 default:
465 LOG(FATAL) << "Unknown instruction set: " << insn_set;
466 }
467}
468
469
Logan Chien8b977d32012-02-21 19:14:55 +0800470} // namespace compiler_llvm
471} // namespace art