blob: aad18fba17b0aca82204921a79526490c9bd3003 [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
Brian Carlstrom641ce032013-01-31 15:21:37 -080017#include "llvm_compilation_unit.h"
Logan Chien8b977d32012-02-21 19:14:55 +080018
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 {
Ian Rogers4c1c2832013-03-04 18:30:13 -080081namespace llvm {
Logan Chien8b977d32012-02-21 19:14:55 +080082
Ian Rogers4c1c2832013-03-04 18:30:13 -080083::llvm::FunctionPass*
Ian Rogers76ae4fe2013-02-27 16:03:41 -080084CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
Ian Rogers89756f22013-03-04 16:40:02 -080085 CompilerDriver* compiler, DexCompilationUnit* dex_compilation_unit);
Shih-wei Liao21d28f52012-06-12 05:55:00 -070086
Ian Rogers4c1c2832013-03-04 18:30:13 -080087::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
Logan Chien8b977d32012-02-21 19:14:55 +080088
89
Ian Rogers89756f22013-03-04 16:40:02 -080090LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm, size_t cunit_idx)
91 : compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx) {
Ian Rogers1212a022013-03-04 10:48:41 -080092 driver_ = NULL;
Ian Rogers89756f22013-03-04 16:40:02 -080093 dex_compilation_unit_ = NULL;
buzbee4df2bbd2012-10-11 14:46:06 -070094 llvm_info_.reset(new LLVMInfo());
95 context_.reset(llvm_info_->GetLLVMContext());
96 module_ = llvm_info_->GetLLVMModule();
TDYa12755e5e6c2012-09-11 15:14:42 -070097
98 // Include the runtime function declaration
99 makeLLVMModuleContents(module_);
100
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800101
102 intrinsic_helper_.reset(new IntrinsicHelper(*context_, *module_));
103
Logan Chien8b977d32012-02-21 19:14:55 +0800104 // Create IRBuilder
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800105 irb_.reset(new IRBuilder(*context_, *module_, *intrinsic_helper_));
TDYa127d668a062012-04-13 12:36:57 -0700106
107 // We always need a switch case, so just use a normal function.
Logan Chien971bf3f2012-05-01 15:47:55 +0800108 switch(GetInstructionSet()) {
TDYa127b08ed122012-06-05 23:51:19 -0700109 default:
110 runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
111 break;
TDYa127d668a062012-04-13 12:36:57 -0700112 case kArm:
TDYa127d668a062012-04-13 12:36:57 -0700113 runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
114 break;
TDYa127b08ed122012-06-05 23:51:19 -0700115 case kThumb2:
116 runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
117 break;
TDYa127d668a062012-04-13 12:36:57 -0700118 case kX86:
119 runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
120 break;
121 }
122
TDYa127d668a062012-04-13 12:36:57 -0700123 irb_->SetRuntimeSupport(runtime_support_.get());
Logan Chien8b977d32012-02-21 19:14:55 +0800124}
125
126
Brian Carlstrom641ce032013-01-31 15:21:37 -0800127LlvmCompilationUnit::~LlvmCompilationUnit() {
Ian Rogers4c1c2832013-03-04 18:30:13 -0800128 ::llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_
TDYa12755e5e6c2012-09-11 15:14:42 -0700129 CHECK(llvm_context != NULL);
Logan Chien8b977d32012-02-21 19:14:55 +0800130}
131
132
Brian Carlstrom641ce032013-01-31 15:21:37 -0800133InstructionSet LlvmCompilationUnit::GetInstructionSet() const {
Logan Chien971bf3f2012-05-01 15:47:55 +0800134 return compiler_llvm_->GetInstructionSet();
Logan Chien8b977d32012-02-21 19:14:55 +0800135}
136
137
Brian Carlstrom641ce032013-01-31 15:21:37 -0800138bool LlvmCompilationUnit::Materialize() {
Logan Chien971bf3f2012-05-01 15:47:55 +0800139 std::string elf_image;
Logan Chien110bcba2012-04-16 19:11:28 +0800140
Ian Rogers4c1c2832013-03-04 18:30:13 -0800141 // Compile and prelink ::llvm::Module
Logan Chien971bf3f2012-05-01 15:47:55 +0800142 if (!MaterializeToString(elf_image)) {
143 LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_;
Logan Chien971bf3f2012-05-01 15:47:55 +0800144 return false;
Logan Chien110bcba2012-04-16 19:11:28 +0800145 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800146
147#if 0
148 // Dump the ELF image for debugging
149 std::string filename(StringPrintf("%s/Art%zu.elf",
150 GetArtCacheOrDie(GetAndroidData()).c_str(),
151 cunit_idx_));
152 UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
153 output->WriteFully(elf_image.data(), elf_image.size());
154#endif
155
156 // Extract the .text section and prelink the code
157 if (!ExtractCodeAndPrelink(elf_image)) {
158 LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_;
Logan Chien971bf3f2012-05-01 15:47:55 +0800159 return false;
160 }
161
Logan Chien971bf3f2012-05-01 15:47:55 +0800162 return true;
Logan Chien110bcba2012-04-16 19:11:28 +0800163}
164
Logan Chien971bf3f2012-05-01 15:47:55 +0800165
Brian Carlstrom641ce032013-01-31 15:21:37 -0800166bool LlvmCompilationUnit::MaterializeToString(std::string& str_buffer) {
Ian Rogers4c1c2832013-03-04 18:30:13 -0800167 ::llvm::raw_string_ostream str_os(str_buffer);
Logan Chien971bf3f2012-05-01 15:47:55 +0800168 return MaterializeToRawOStream(str_os);
169}
170
171
Ian Rogers4c1c2832013-03-04 18:30:13 -0800172bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_stream) {
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700173 // Lookup the LLVM target
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800174 std::string target_triple;
175 std::string target_cpu;
176 std::string target_attr;
Ian Rogers1212a022013-03-04 10:48:41 -0800177 CompilerDriver::InstructionSetToLLVMTarget(GetInstructionSet(), target_triple, target_cpu, target_attr);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700178
179 std::string errmsg;
Ian Rogers4c1c2832013-03-04 18:30:13 -0800180 const ::llvm::Target* target =
181 ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700182
183 CHECK(target != NULL) << errmsg;
184
185 // Target options
Ian Rogers4c1c2832013-03-04 18:30:13 -0800186 ::llvm::TargetOptions target_options;
187 target_options.FloatABIType = ::llvm::FloatABI::Soft;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700188 target_options.NoFramePointerElim = true;
189 target_options.NoFramePointerElimNonLeaf = true;
190 target_options.UseSoftFloat = false;
TDYa1273978da52012-05-19 07:45:39 -0700191 target_options.EnableFastISel = false;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700192
Ian Rogers4c1c2832013-03-04 18:30:13 -0800193 // Create the ::llvm::TargetMachine
194 ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine(
Shih-wei Liao53519bf2012-06-17 03:45:00 -0700195 target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
Ian Rogers4c1c2832013-03-04 18:30:13 -0800196 ::llvm::Reloc::Static, ::llvm::CodeModel::Small,
197 ::llvm::CodeGenOpt::Aggressive));
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700198
Logan Chienb6bed0b2012-05-04 15:03:56 +0800199 CHECK(target_machine.get() != NULL) << "Failed to create target machine";
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700200
201 // Add target data
Ian Rogers4c1c2832013-03-04 18:30:13 -0800202 const ::llvm::TargetData* target_data = target_machine->getTargetData();
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700203
204 // PassManager for code generation passes
Ian Rogers4c1c2832013-03-04 18:30:13 -0800205 ::llvm::PassManager pm;
206 pm.add(new ::llvm::TargetData(*target_data));
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700207
208 // FunctionPassManager for optimization pass
Ian Rogers4c1c2832013-03-04 18:30:13 -0800209 ::llvm::FunctionPassManager fpm(module_);
210 fpm.add(new ::llvm::TargetData(*target_data));
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700211
TDYa127f15b0ab2012-05-11 21:01:36 -0700212 if (bitcode_filename_.empty()) {
213 // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
214 // regular FunctionPass.
buzbee4df2bbd2012-10-11 14:46:06 -0700215 fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
Ian Rogers89756f22013-03-04 16:40:02 -0800216 driver_, dex_compilation_unit_));
TDYa127f15b0ab2012-05-11 21:01:36 -0700217 } else {
Ian Rogers4c1c2832013-03-04 18:30:13 -0800218 ::llvm::FunctionPassManager fpm2(module_);
buzbee4df2bbd2012-10-11 14:46:06 -0700219 fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
Ian Rogers89756f22013-03-04 16:40:02 -0800220 driver_, dex_compilation_unit_));
TDYa127f15b0ab2012-05-11 21:01:36 -0700221 fpm2.doInitialization();
Ian Rogers4c1c2832013-03-04 18:30:13 -0800222 for (::llvm::Module::iterator F = module_->begin(), E = module_->end();
TDYa127f15b0ab2012-05-11 21:01:36 -0700223 F != E; ++F) {
224 fpm2.run(*F);
225 }
226 fpm2.doFinalization();
TDYa127f15b0ab2012-05-11 21:01:36 -0700227
228 // Write bitcode to file
229 std::string errmsg;
230
Ian Rogers4c1c2832013-03-04 18:30:13 -0800231 ::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
232 new ::llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
233 ::llvm::raw_fd_ostream::F_Binary));
TDYa127f15b0ab2012-05-11 21:01:36 -0700234
235
236 if (!errmsg.empty()) {
237 LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
238 return false;
239 }
240
Ian Rogers4c1c2832013-03-04 18:30:13 -0800241 ::llvm::WriteBitcodeToFile(module_, out_file->os());
TDYa127f15b0ab2012-05-11 21:01:36 -0700242 out_file->keep();
243 }
244
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700245 // Add optimization pass
Ian Rogers4c1c2832013-03-04 18:30:13 -0800246 ::llvm::PassManagerBuilder pm_builder;
TDYa1279a129452012-07-19 03:10:08 -0700247 // TODO: Use inliner after we can do IPO.
248 pm_builder.Inliner = NULL;
Ian Rogers4c1c2832013-03-04 18:30:13 -0800249 //pm_builder.Inliner = ::llvm::createFunctionInliningPass();
250 //pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
251 //pm_builder.Inliner = ::llvm::createPartialInliningPass();
Shih-wei Liao415576b2012-04-23 15:28:53 -0700252 pm_builder.OptLevel = 3;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700253 pm_builder.DisableSimplifyLibCalls = 1;
TDYa127e4c2ccc2012-05-13 21:10:36 -0700254 pm_builder.DisableUnitAtATime = 1;
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700255 pm_builder.populateFunctionPassManager(fpm);
TDYa127ce9c3172012-05-15 06:09:27 -0700256 pm_builder.populateModulePassManager(pm);
Ian Rogers4c1c2832013-03-04 18:30:13 -0800257 pm.add(::llvm::createStripDeadPrototypesPass());
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700258
259 // Add passes to emit ELF image
260 {
Ian Rogers4c1c2832013-03-04 18:30:13 -0800261 ::llvm::formatted_raw_ostream formatted_os(out_stream, false);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700262
263 // Ask the target to add backend passes as necessary.
264 if (target_machine->addPassesToEmitFile(pm,
265 formatted_os,
Ian Rogers4c1c2832013-03-04 18:30:13 -0800266 ::llvm::TargetMachine::CGFT_ObjectFile,
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700267 true)) {
268 LOG(FATAL) << "Unable to generate ELF for this target";
269 return false;
270 }
271
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700272 // Run the per-function optimization
273 fpm.doInitialization();
Ian Rogers4c1c2832013-03-04 18:30:13 -0800274 for (::llvm::Module::iterator F = module_->begin(), E = module_->end();
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700275 F != E; ++F) {
276 fpm.run(*F);
277 }
278 fpm.doFinalization();
279
280 // Run the code generation passes
Logan Chien799ef4f2012-04-23 00:17:47 +0800281 pm.run(*module_);
Shih-wei Liaod7726e42012-04-20 15:23:36 -0700282 }
283
284 return true;
285}
Logan Chien110bcba2012-04-16 19:11:28 +0800286
Brian Carlstrom641ce032013-01-31 15:21:37 -0800287bool LlvmCompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
Shih-wei Liao02a1e352012-06-30 00:42:07 -0700288 if (GetInstructionSet() == kX86) {
289 compiled_code_.push_back(0xccU);
290 compiled_code_.push_back(0xccU);
291 compiled_code_.push_back(0xccU);
292 compiled_code_.push_back(0xccU);
293 return true;
294 }
295
Ian Rogers4c1c2832013-03-04 18:30:13 -0800296 ::llvm::OwningPtr< ::llvm::MemoryBuffer> elf_image_buff(
297 ::llvm::MemoryBuffer::getMemBuffer(::llvm::StringRef(elf_image.data(),
Logan Chien971bf3f2012-05-01 15:47:55 +0800298 elf_image.size())));
299
Ian Rogers4c1c2832013-03-04 18:30:13 -0800300 ::llvm::OwningPtr< ::llvm::object::ObjectFile> elf_file(
301 ::llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take()));
Logan Chien971bf3f2012-05-01 15:47:55 +0800302
Ian Rogers4c1c2832013-03-04 18:30:13 -0800303 ::llvm::error_code ec;
Logan Chien971bf3f2012-05-01 15:47:55 +0800304
305 const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable();
306
Ian Rogers4c1c2832013-03-04 18:30:13 -0800307 for (::llvm::object::section_iterator
Logan Chien971bf3f2012-05-01 15:47:55 +0800308 sec_iter = elf_file->begin_sections(),
309 sec_end = elf_file->end_sections();
310 sec_iter != sec_end; sec_iter.increment(ec)) {
311
312 CHECK(ec == 0) << "Failed to read section because " << ec.message();
313
314 // Read the section information
Ian Rogers4c1c2832013-03-04 18:30:13 -0800315 ::llvm::StringRef name;
Logan Chien971bf3f2012-05-01 15:47:55 +0800316 uint64_t alignment = 0u;
317 uint64_t size = 0u;
318
319 CHECK(sec_iter->getName(name) == 0);
320 CHECK(sec_iter->getSize(size) == 0);
321 CHECK(sec_iter->getAlignment(alignment) == 0);
322
323 if (name == ".data" || name == ".bss" || name == ".rodata") {
324 if (size > 0) {
325 LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty "
326 << name.str() << " section";
327 }
328
329 } else if (name == "" || name == ".rel.text" ||
330 name == ".ARM.attributes" || name == ".symtab" ||
331 name == ".strtab" || name == ".shstrtab") {
332 // We can ignore these sections. We don't have to copy them into
333 // the result Oat file.
334
335 } else if (name == ".text") {
336 // Ensure the alignment requirement is less than or equal to
337 // kArchAlignment
338 CheckCodeAlign(alignment);
339
340 // Copy the compiled code
Ian Rogers4c1c2832013-03-04 18:30:13 -0800341 ::llvm::StringRef contents;
Logan Chien971bf3f2012-05-01 15:47:55 +0800342 CHECK(sec_iter->getContents(contents) == 0);
343
344 copy(contents.data(),
345 contents.data() + contents.size(),
346 back_inserter(compiled_code_));
347
348 // Prelink the compiled code
Ian Rogers4c1c2832013-03-04 18:30:13 -0800349 for (::llvm::object::relocation_iterator
Logan Chien971bf3f2012-05-01 15:47:55 +0800350 rel_iter = sec_iter->begin_relocations(),
351 rel_end = sec_iter->end_relocations(); rel_iter != rel_end;
352 rel_iter.increment(ec)) {
353
354 CHECK(ec == 0) << "Failed to read relocation because " << ec.message();
355
356 // Read the relocation information
Ian Rogers4c1c2832013-03-04 18:30:13 -0800357 ::llvm::object::SymbolRef sym_ref;
Logan Chien971bf3f2012-05-01 15:47:55 +0800358 uint64_t rel_offset = 0;
359 uint64_t rel_type = 0;
360 int64_t rel_addend = 0;
361
362 CHECK(rel_iter->getSymbol(sym_ref) == 0);
363 CHECK(rel_iter->getOffset(rel_offset) == 0);
364 CHECK(rel_iter->getType(rel_type) == 0);
365 CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0);
366
367 // Read the symbol related to this relocation fixup
Ian Rogers4c1c2832013-03-04 18:30:13 -0800368 ::llvm::StringRef sym_name;
Logan Chien971bf3f2012-05-01 15:47:55 +0800369 CHECK(sym_ref.getName(sym_name) == 0);
370
371 // Relocate the fixup.
372 // TODO: Support more relocation type.
Ian Rogers4c1c2832013-03-04 18:30:13 -0800373 CHECK(rel_type == ::llvm::ELF::R_ARM_ABS32);
Logan Chien971bf3f2012-05-01 15:47:55 +0800374 CHECK_LE(rel_offset + 4, compiled_code_.size());
375
376 uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str());
377 uintptr_t final_addr = dest_addr + rel_addend;
378 compiled_code_[rel_offset] = final_addr & 0xff;
379 compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff;
380 compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff;
381 compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff;
382 }
383
384 } else {
385 LOG(WARNING) << "Unexpected section: " << name.str();
386 }
387 }
388
389 return true;
390}
391
392
393// Check whether the align is less than or equal to the code alignment of
394// that architecture. Since the Oat writer only guarantee that the compiled
395// method being aligned to kArchAlignment, we have no way to align the ELf
396// section if the section alignment is greater than kArchAlignment.
Brian Carlstrom641ce032013-01-31 15:21:37 -0800397void LlvmCompilationUnit::CheckCodeAlign(uint32_t align) const {
Logan Chien971bf3f2012-05-01 15:47:55 +0800398 InstructionSet insn_set = GetInstructionSet();
399 switch (insn_set) {
400 case kThumb2:
401 case kArm:
402 CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
403 break;
404
405 case kX86:
406 CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
407 break;
408
409 case kMips:
410 CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
411 break;
412
413 default:
414 LOG(FATAL) << "Unknown instruction set: " << insn_set;
415 }
416}
417
418
Ian Rogers4c1c2832013-03-04 18:30:13 -0800419} // namespace llvm
Logan Chien8b977d32012-02-21 19:14:55 +0800420} // namespace art