1 /* 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 // TODO: TargetLibraryInfo is included before sys/... because on Android bionic does #define tricks like: 18 // 19 // #define stat64 stat 20 // #define fstat64 fstat 21 // #define lstat64 lstat 22 // 23 // which causes grief. bionic probably should not do that. 24 #include <llvm/Target/TargetLibraryInfo.h> 25 26 #include "llvm_compilation_unit.h" 27 28 #include <sys/types.h> 29 #include <sys/wait.h> 30 #include <unistd.h> 31 32 #include <string> 33 34 #include <llvm/ADT/OwningPtr.h> 35 #include <llvm/ADT/StringSet.h> 36 #include <llvm/ADT/Triple.h> 37 #include <llvm/Analysis/CallGraph.h> 38 #include <llvm/Analysis/CallGraphSCCPass.h> 39 #include <llvm/Analysis/Dominators.h> 40 #include <llvm/Analysis/LoopInfo.h> 41 #include <llvm/Analysis/LoopPass.h> 42 #include <llvm/Analysis/RegionPass.h> 43 #include <llvm/Analysis/ScalarEvolution.h> 44 #include <llvm/Analysis/Verifier.h> 45 #include <llvm/Assembly/PrintModulePass.h> 46 #include <llvm/Bitcode/ReaderWriter.h> 47 #include <llvm/CodeGen/MachineFrameInfo.h> 48 #include <llvm/CodeGen/MachineFunction.h> 49 #include <llvm/CodeGen/MachineFunctionPass.h> 50 #include <llvm/DebugInfo.h> 51 #include <llvm/IR/DataLayout.h> 52 #include <llvm/IR/DerivedTypes.h> 53 #include <llvm/IR/LLVMContext.h> 54 #include <llvm/IR/Module.h> 55 #include <llvm/Object/ObjectFile.h> 56 #include <llvm/PassManager.h> 57 #include <llvm/Support/Debug.h> 58 #include <llvm/Support/ELF.h> 59 #include <llvm/Support/FormattedStream.h> 60 #include <llvm/Support/ManagedStatic.h> 61 #include <llvm/Support/MemoryBuffer.h> 62 #include <llvm/Support/PassNameParser.h> 63 #include <llvm/Support/PluginLoader.h> 64 #include <llvm/Support/PrettyStackTrace.h> 65 #include <llvm/Support/Signals.h> 66 #include <llvm/Support/SystemUtils.h> 67 #include <llvm/Support/TargetRegistry.h> 68 #include <llvm/Support/TargetSelect.h> 69 #include <llvm/Support/ToolOutputFile.h> 70 #include <llvm/Support/raw_ostream.h> 71 #include <llvm/Support/system_error.h> 72 #include <llvm/Target/TargetMachine.h> 73 #include <llvm/Transforms/IPO.h> 74 #include <llvm/Transforms/IPO/PassManagerBuilder.h> 75 #include <llvm/Transforms/Scalar.h> 76 77 #include "base/logging.h" 78 #include "base/unix_file/fd_file.h" 79 #include "compiled_method.h" 80 #include "compiler_llvm.h" 81 #include "instruction_set.h" 82 #include "ir_builder.h" 83 #include "os.h" 84 #include "runtime_support_builder_arm.h" 85 #include "runtime_support_builder_thumb2.h" 86 #include "runtime_support_builder_x86.h" 87 #include "utils_llvm.h" 88 89 namespace art { 90 namespace llvm { 91 92 ::llvm::FunctionPass* 93 CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb, 94 CompilerDriver* compiler, const DexCompilationUnit* dex_compilation_unit); 95 96 ::llvm::Module* makeLLVMModuleContents(::llvm::Module* module); 97 98 99 LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm, size_t cunit_id) 100 : compiler_llvm_(compiler_llvm), cunit_id_(cunit_id) { 101 driver_ = NULL; 102 dex_compilation_unit_ = NULL; 103 llvm_info_.reset(new LLVMInfo()); 104 context_.reset(llvm_info_->GetLLVMContext()); 105 module_ = llvm_info_->GetLLVMModule(); 106 107 // Include the runtime function declaration 108 makeLLVMModuleContents(module_); 109 110 111 intrinsic_helper_.reset(new IntrinsicHelper(*context_, *module_)); 112 113 // Create IRBuilder 114 irb_.reset(new IRBuilder(*context_, *module_, *intrinsic_helper_)); 115 116 // We always need a switch case, so just use a normal function. 117 switch (GetInstructionSet()) { 118 default: 119 runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_)); 120 break; 121 case kArm: 122 runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_)); 123 break; 124 case kThumb2: 125 runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_)); 126 break; 127 case kX86: 128 runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_)); 129 break; 130 } 131 132 irb_->SetRuntimeSupport(runtime_support_.get()); 133 } 134 135 136 LlvmCompilationUnit::~LlvmCompilationUnit() { 137 ::llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_ 138 CHECK(llvm_context != NULL); 139 } 140 141 142 InstructionSet LlvmCompilationUnit::GetInstructionSet() const { 143 return compiler_llvm_->GetInstructionSet(); 144 } 145 146 147 static std::string DumpDirectory() { 148 if (kIsTargetBuild) { 149 return GetDalvikCacheOrDie(GetAndroidData()); 150 } 151 return "/tmp"; 152 } 153 154 void LlvmCompilationUnit::DumpBitcodeToFile() { 155 std::string bitcode; 156 DumpBitcodeToString(bitcode); 157 std::string filename(StringPrintf("%s/Art%u.bc", DumpDirectory().c_str(), cunit_id_)); 158 UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str())); 159 output->WriteFully(bitcode.data(), bitcode.size()); 160 LOG(INFO) << ".bc file written successfully: " << filename; 161 } 162 163 void LlvmCompilationUnit::DumpBitcodeToString(std::string& str_buffer) { 164 ::llvm::raw_string_ostream str_os(str_buffer); 165 ::llvm::WriteBitcodeToFile(module_, str_os); 166 } 167 168 bool LlvmCompilationUnit::Materialize() { 169 const bool kDumpBitcode = false; 170 if (kDumpBitcode) { 171 // Dump the bitcode for debugging 172 DumpBitcodeToFile(); 173 } 174 175 // Compile and prelink ::llvm::Module 176 if (!MaterializeToString(elf_object_)) { 177 LOG(ERROR) << "Failed to materialize compilation unit " << cunit_id_; 178 return false; 179 } 180 181 const bool kDumpELF = false; 182 if (kDumpELF) { 183 // Dump the ELF image for debugging 184 std::string filename(StringPrintf("%s/Art%u.o", DumpDirectory().c_str(), cunit_id_)); 185 UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str())); 186 output->WriteFully(elf_object_.data(), elf_object_.size()); 187 LOG(INFO) << ".o file written successfully: " << filename; 188 } 189 190 return true; 191 } 192 193 194 bool LlvmCompilationUnit::MaterializeToString(std::string& str_buffer) { 195 ::llvm::raw_string_ostream str_os(str_buffer); 196 return MaterializeToRawOStream(str_os); 197 } 198 199 200 bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_stream) { 201 // Lookup the LLVM target 202 std::string target_triple; 203 std::string target_cpu; 204 std::string target_attr; 205 CompilerDriver::InstructionSetToLLVMTarget(GetInstructionSet(), target_triple, target_cpu, target_attr); 206 207 std::string errmsg; 208 const ::llvm::Target* target = 209 ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg); 210 211 CHECK(target != NULL) << errmsg; 212 213 // Target options 214 ::llvm::TargetOptions target_options; 215 target_options.FloatABIType = ::llvm::FloatABI::Soft; 216 target_options.NoFramePointerElim = true; 217 target_options.UseSoftFloat = false; 218 target_options.EnableFastISel = false; 219 220 // Create the ::llvm::TargetMachine 221 ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine( 222 target->createTargetMachine(target_triple, target_cpu, target_attr, target_options, 223 ::llvm::Reloc::Static, ::llvm::CodeModel::Small, 224 ::llvm::CodeGenOpt::Aggressive)); 225 226 CHECK(target_machine.get() != NULL) << "Failed to create target machine"; 227 228 // Add target data 229 const ::llvm::DataLayout* data_layout = target_machine->getDataLayout(); 230 231 // PassManager for code generation passes 232 ::llvm::PassManager pm; 233 pm.add(new ::llvm::DataLayout(*data_layout)); 234 235 // FunctionPassManager for optimization pass 236 ::llvm::FunctionPassManager fpm(module_); 237 fpm.add(new ::llvm::DataLayout(*data_layout)); 238 239 if (bitcode_filename_.empty()) { 240 // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the 241 // regular FunctionPass. 242 fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(), 243 driver_, dex_compilation_unit_)); 244 } else { 245 ::llvm::FunctionPassManager fpm2(module_); 246 fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(), 247 driver_, dex_compilation_unit_)); 248 fpm2.doInitialization(); 249 for (::llvm::Module::iterator F = module_->begin(), E = module_->end(); 250 F != E; ++F) { 251 fpm2.run(*F); 252 } 253 fpm2.doFinalization(); 254 255 // Write bitcode to file 256 std::string errmsg; 257 258 ::llvm::OwningPtr< ::llvm::tool_output_file> out_file( 259 new ::llvm::tool_output_file(bitcode_filename_.c_str(), errmsg, 260 ::llvm::sys::fs::F_Binary)); 261 262 263 if (!errmsg.empty()) { 264 LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; 265 return false; 266 } 267 268 ::llvm::WriteBitcodeToFile(module_, out_file->os()); 269 out_file->keep(); 270 } 271 272 // Add optimization pass 273 ::llvm::PassManagerBuilder pm_builder; 274 // TODO: Use inliner after we can do IPO. 275 pm_builder.Inliner = NULL; 276 // pm_builder.Inliner = ::llvm::createFunctionInliningPass(); 277 // pm_builder.Inliner = ::llvm::createAlwaysInlinerPass(); 278 // pm_builder.Inliner = ::llvm::createPartialInliningPass(); 279 pm_builder.OptLevel = 3; 280 pm_builder.DisableUnitAtATime = 1; 281 pm_builder.populateFunctionPassManager(fpm); 282 pm_builder.populateModulePassManager(pm); 283 pm.add(::llvm::createStripDeadPrototypesPass()); 284 285 // Add passes to emit ELF image 286 { 287 ::llvm::formatted_raw_ostream formatted_os(out_stream, false); 288 289 // Ask the target to add backend passes as necessary. 290 if (target_machine->addPassesToEmitFile(pm, 291 formatted_os, 292 ::llvm::TargetMachine::CGFT_ObjectFile, 293 true)) { 294 LOG(FATAL) << "Unable to generate ELF for this target"; 295 return false; 296 } 297 298 // Run the per-function optimization 299 fpm.doInitialization(); 300 for (::llvm::Module::iterator F = module_->begin(), E = module_->end(); 301 F != E; ++F) { 302 fpm.run(*F); 303 } 304 fpm.doFinalization(); 305 306 // Run the code generation passes 307 pm.run(*module_); 308 } 309 310 return true; 311 } 312 313 // Check whether the align is less than or equal to the code alignment of 314 // that architecture. Since the Oat writer only guarantee that the compiled 315 // method being aligned to kArchAlignment, we have no way to align the ELf 316 // section if the section alignment is greater than kArchAlignment. 317 void LlvmCompilationUnit::CheckCodeAlign(uint32_t align) const { 318 InstructionSet insn_set = GetInstructionSet(); 319 switch (insn_set) { 320 case kThumb2: 321 case kArm: 322 CHECK_LE(align, static_cast<uint32_t>(kArmAlignment)); 323 break; 324 325 case kX86: 326 CHECK_LE(align, static_cast<uint32_t>(kX86Alignment)); 327 break; 328 329 case kMips: 330 CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment)); 331 break; 332 333 default: 334 LOG(FATAL) << "Unknown instruction set: " << insn_set; 335 } 336 } 337 338 339 } // namespace llvm 340 } // namespace art 341