| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 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 | #include "compilation_unit.h" | 
|  | 18 |  | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 19 | #include "compiled_method.h" | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 20 | #include "file.h" | 
| Elliott Hughes | 0f3c553 | 2012-03-30 14:51:51 -0700 | [diff] [blame] | 21 | #include "instruction_set.h" | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 22 | #include "ir_builder.h" | 
|  | 23 | #include "logging.h" | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 24 | #include "os.h" | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 25 |  | 
| TDYa127 | d668a06 | 2012-04-13 12:36:57 -0700 | [diff] [blame] | 26 | #include "runtime_support_builder_arm.h" | 
|  | 27 | #include "runtime_support_builder_x86.h" | 
|  | 28 |  | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 29 | #include <llvm/ADT/OwningPtr.h> | 
|  | 30 | #include <llvm/ADT/StringSet.h> | 
|  | 31 | #include <llvm/ADT/Triple.h> | 
|  | 32 | #include <llvm/Analysis/CallGraph.h> | 
|  | 33 | #include <llvm/Analysis/DebugInfo.h> | 
| TDYa127 | f15b0ab | 2012-05-11 21:01:36 -0700 | [diff] [blame] | 34 | #include <llvm/Analysis/Dominators.h> | 
|  | 35 | #include <llvm/Analysis/LoopInfo.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 36 | #include <llvm/Analysis/LoopPass.h> | 
|  | 37 | #include <llvm/Analysis/RegionPass.h> | 
| TDYa127 | f15b0ab | 2012-05-11 21:01:36 -0700 | [diff] [blame] | 38 | #include <llvm/Analysis/ScalarEvolution.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 39 | #include <llvm/Analysis/Verifier.h> | 
|  | 40 | #include <llvm/Assembly/PrintModulePass.h> | 
|  | 41 | #include <llvm/Bitcode/ReaderWriter.h> | 
|  | 42 | #include <llvm/CallGraphSCCPass.h> | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 43 | #include <llvm/CodeGen/MachineFrameInfo.h> | 
|  | 44 | #include <llvm/CodeGen/MachineFunction.h> | 
|  | 45 | #include <llvm/CodeGen/MachineFunctionPass.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 46 | #include <llvm/DerivedTypes.h> | 
|  | 47 | #include <llvm/LLVMContext.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 48 | #include <llvm/Module.h> | 
|  | 49 | #include <llvm/PassManager.h> | 
|  | 50 | #include <llvm/Support/Debug.h> | 
|  | 51 | #include <llvm/Support/FormattedStream.h> | 
|  | 52 | #include <llvm/Support/ManagedStatic.h> | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 53 | #include <llvm/Support/MemoryBuffer.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 54 | #include <llvm/Support/PassNameParser.h> | 
|  | 55 | #include <llvm/Support/PluginLoader.h> | 
|  | 56 | #include <llvm/Support/PrettyStackTrace.h> | 
|  | 57 | #include <llvm/Support/Signals.h> | 
|  | 58 | #include <llvm/Support/SystemUtils.h> | 
|  | 59 | #include <llvm/Support/TargetRegistry.h> | 
|  | 60 | #include <llvm/Support/TargetSelect.h> | 
|  | 61 | #include <llvm/Support/ToolOutputFile.h> | 
|  | 62 | #include <llvm/Support/raw_ostream.h> | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 63 | #include <llvm/Support/system_error.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 64 | #include <llvm/Target/TargetData.h> | 
|  | 65 | #include <llvm/Target/TargetLibraryInfo.h> | 
|  | 66 | #include <llvm/Target/TargetMachine.h> | 
| Shih-wei Liao | f1cb9a5 | 2012-04-20 01:49:18 -0700 | [diff] [blame] | 67 | #include <llvm/Transforms/IPO.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 68 | #include <llvm/Transforms/IPO/PassManagerBuilder.h> | 
| TDYa127 | f15b0ab | 2012-05-11 21:01:36 -0700 | [diff] [blame] | 69 | #include <llvm/Transforms/Scalar.h> | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 70 |  | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 71 | #include <sys/types.h> | 
|  | 72 | #include <sys/wait.h> | 
|  | 73 | #include <unistd.h> | 
|  | 74 |  | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 75 | #include <string> | 
|  | 76 |  | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 77 | namespace { | 
|  | 78 |  | 
|  | 79 | class UpdateFrameSizePass : public llvm::MachineFunctionPass { | 
|  | 80 | public: | 
|  | 81 | static char ID; | 
|  | 82 |  | 
|  | 83 | UpdateFrameSizePass() : llvm::MachineFunctionPass(ID), cunit_(NULL) { | 
|  | 84 | LOG(FATAL) << "Unexpected instantiation of UpdateFrameSizePass"; | 
|  | 85 | // NOTE: We have to declare this constructor for llvm::RegisterPass, but | 
|  | 86 | // this constructor won't work because we have no information on | 
|  | 87 | // CompilationUnit.  Thus, we should place a LOG(FATAL) here. | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | UpdateFrameSizePass(art::compiler_llvm::CompilationUnit* cunit) | 
|  | 91 | : llvm::MachineFunctionPass(ID), cunit_(cunit) { | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | virtual bool runOnMachineFunction(llvm::MachineFunction &MF) { | 
|  | 95 | cunit_->UpdateFrameSizeInBytes(MF.getFunction(), | 
|  | 96 | MF.getFrameInfo()->getStackSize()); | 
|  | 97 | return false; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | private: | 
|  | 101 | art::compiler_llvm::CompilationUnit* cunit_; | 
|  | 102 | }; | 
|  | 103 |  | 
|  | 104 | char UpdateFrameSizePass::ID = 0; | 
|  | 105 |  | 
|  | 106 | llvm::RegisterPass<UpdateFrameSizePass> reg_update_frame_size_pass_( | 
|  | 107 | "update-frame-size", "Update frame size pass", false, false); | 
|  | 108 |  | 
| TDYa127 | f15b0ab | 2012-05-11 21:01:36 -0700 | [diff] [blame] | 109 |  | 
|  | 110 | // TODO: We may need something to manage these passes. | 
|  | 111 | // TODO: We need high-level IR to analysis and do this at the IRBuilder level. | 
|  | 112 | class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass { | 
|  | 113 | public: | 
|  | 114 | static char ID; | 
|  | 115 |  | 
|  | 116 | AddSuspendCheckToLoopLatchPass() : llvm::LoopPass(ID), irb_(NULL) { | 
|  | 117 | LOG(FATAL) << "Unexpected instantiation of AddSuspendCheckToLoopLatchPass"; | 
|  | 118 | // NOTE: We have to declare this constructor for llvm::RegisterPass, but | 
|  | 119 | // this constructor won't work because we have no information on | 
|  | 120 | // IRBuilder.  Thus, we should place a LOG(FATAL) here. | 
|  | 121 | } | 
|  | 122 |  | 
|  | 123 | AddSuspendCheckToLoopLatchPass(art::compiler_llvm::IRBuilder* irb) | 
|  | 124 | : llvm::LoopPass(ID), irb_(irb) { | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const { | 
|  | 128 | AU.addRequiredID(llvm::LoopSimplifyID); | 
|  | 129 |  | 
|  | 130 | AU.addPreserved<llvm::DominatorTree>(); | 
|  | 131 | AU.addPreserved<llvm::LoopInfo>(); | 
|  | 132 | AU.addPreservedID(llvm::LoopSimplifyID); | 
|  | 133 | AU.addPreserved<llvm::ScalarEvolution>(); | 
|  | 134 | AU.addPreservedID(llvm::BreakCriticalEdgesID); | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) { | 
|  | 138 | CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!"; | 
|  | 139 | llvm::BasicBlock* bb = loop->getLoopLatch(); | 
|  | 140 | CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist."; | 
|  | 141 |  | 
|  | 142 | irb_->SetInsertPoint(bb->getTerminator()); | 
|  | 143 |  | 
|  | 144 | using namespace art::compiler_llvm::runtime_support; | 
|  | 145 | llvm::Value* runtime_func = irb_->GetRuntime(TestSuspend); | 
|  | 146 | llvm::Value* thread_object_addr = irb_->CreateCall(irb_->GetRuntime(GetCurrentThread)); | 
|  | 147 | irb_->CreateCall(runtime_func, thread_object_addr); | 
|  | 148 |  | 
|  | 149 | return true; | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | private: | 
|  | 153 | art::compiler_llvm::IRBuilder* irb_; | 
|  | 154 | }; | 
|  | 155 |  | 
|  | 156 | char AddSuspendCheckToLoopLatchPass::ID = 0; | 
|  | 157 |  | 
|  | 158 | llvm::RegisterPass<AddSuspendCheckToLoopLatchPass> reg_add_suspend_check_to_loop_latch_pass_( | 
|  | 159 | "add-suspend-check-to-loop-latch", "Add suspend check to loop latch pass", false, false); | 
|  | 160 |  | 
|  | 161 |  | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 162 | } // end anonymous namespace | 
|  | 163 |  | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 164 | namespace art { | 
|  | 165 | namespace compiler_llvm { | 
|  | 166 |  | 
|  | 167 | llvm::Module* makeLLVMModuleContents(llvm::Module* module); | 
|  | 168 |  | 
|  | 169 |  | 
| Logan Chien | 6546ec5 | 2012-03-17 20:08:29 +0800 | [diff] [blame] | 170 | CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx) | 
| Logan Chien | 8ba2fc5 | 2012-04-23 09:10:46 +0800 | [diff] [blame] | 171 | : cunit_lock_("compilation_unit_lock"), insn_set_(insn_set), elf_idx_(elf_idx), | 
|  | 172 | context_(new llvm::LLVMContext()), mem_usage_(0), num_elf_funcs_(0) { | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 173 |  | 
|  | 174 | // Create the module and include the runtime function declaration | 
|  | 175 | module_ = new llvm::Module("art", *context_); | 
|  | 176 | makeLLVMModuleContents(module_); | 
|  | 177 |  | 
|  | 178 | // Create IRBuilder | 
|  | 179 | irb_.reset(new IRBuilder(*context_, *module_)); | 
| TDYa127 | d668a06 | 2012-04-13 12:36:57 -0700 | [diff] [blame] | 180 |  | 
|  | 181 | // We always need a switch case, so just use a normal function. | 
|  | 182 | switch(insn_set_) { | 
|  | 183 | default: | 
|  | 184 | runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_)); | 
|  | 185 | break; | 
|  | 186 | case kArm: | 
|  | 187 | case kThumb2: | 
|  | 188 | runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_)); | 
|  | 189 | break; | 
|  | 190 | case kX86: | 
|  | 191 | runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_)); | 
|  | 192 | break; | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | runtime_support_->OptimizeRuntimeSupport(); | 
|  | 196 |  | 
|  | 197 | irb_->SetRuntimeSupport(runtime_support_.get()); | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 198 | } | 
|  | 199 |  | 
|  | 200 |  | 
|  | 201 | CompilationUnit::~CompilationUnit() { | 
|  | 202 | } | 
|  | 203 |  | 
|  | 204 |  | 
| Logan Chien | 08e1ba3 | 2012-05-08 15:08:51 +0800 | [diff] [blame] | 205 | bool CompilationUnit::Materialize(size_t thread_count) { | 
| Logan Chien | 8ba2fc5 | 2012-04-23 09:10:46 +0800 | [diff] [blame] | 206 | MutexLock GUARD(cunit_lock_); | 
|  | 207 |  | 
| Logan Chien | 08e1ba3 | 2012-05-08 15:08:51 +0800 | [diff] [blame] | 208 | if (thread_count == 1) { | 
|  | 209 | llvm::raw_string_ostream str_os(elf_image_); | 
| Logan Chien | b1bab1c | 2012-05-11 11:05:45 +0800 | [diff] [blame^] | 210 | bool success = MaterializeToFile(str_os); | 
| TDYa127 | a22ea03 | 2012-05-09 12:20:01 -0700 | [diff] [blame] | 211 | LOG(INFO) << "Compilation Unit: " << elf_idx_ << (success ? " (done)" : " (failed)"); | 
| TDYa127 | 388a83b | 2012-05-09 18:56:22 -0700 | [diff] [blame] | 212 |  | 
|  | 213 | // Free the resources | 
|  | 214 | context_.reset(NULL); | 
|  | 215 | irb_.reset(NULL); | 
|  | 216 | module_ = NULL; | 
|  | 217 |  | 
| TDYa127 | a22ea03 | 2012-05-09 12:20:01 -0700 | [diff] [blame] | 218 | return success; | 
| Logan Chien | 08e1ba3 | 2012-05-08 15:08:51 +0800 | [diff] [blame] | 219 | } | 
|  | 220 |  | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 221 | // Prepare the pipe between parent process and child process | 
|  | 222 | int pipe_fd[2]; | 
|  | 223 | if (pipe(pipe_fd) == -1) { | 
| Shih-wei Liao | e8ecce7 | 2012-04-23 15:00:32 -0700 | [diff] [blame] | 224 | PLOG(FATAL) << "Failed to create pipe for CompilerWorker"; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 225 | return false; | 
|  | 226 | } | 
| Shih-wei Liao | 1776572 | 2012-04-17 16:42:19 -0700 | [diff] [blame] | 227 |  | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 228 | // Fork a process to do the compilation | 
|  | 229 | pid_t pid = fork(); | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 230 | if (pid < 0) { | 
|  | 231 | close(pipe_fd[0]); | 
|  | 232 | close(pipe_fd[1]); | 
|  | 233 | PLOG(FATAL) << "Failed to fork a process to do the compilation"; | 
|  | 234 | return false; | 
|  | 235 |  | 
|  | 236 | } else if (pid == 0) { // Child process | 
|  | 237 | // Close the unused pipe read end | 
|  | 238 | close(pipe_fd[0]); | 
|  | 239 |  | 
|  | 240 | // Change process groups, so we don't get ripped by ProcessManager | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 241 | setpgid(0, 0); | 
| Logan Chien | b9eaeea | 2012-03-17 19:45:01 +0800 | [diff] [blame] | 242 |  | 
| Logan Chien | 08e1ba3 | 2012-05-08 15:08:51 +0800 | [diff] [blame] | 243 | llvm::raw_fd_ostream fd_os(pipe_fd[1], /* shouldClose */true); | 
|  | 244 |  | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 245 | // TODO: Should use exec* family instead of invoking a function. | 
|  | 246 | // Forward our compilation request to bcc. | 
| Logan Chien | b1bab1c | 2012-05-11 11:05:45 +0800 | [diff] [blame^] | 247 | exit(static_cast<int>(!MaterializeToFile(fd_os))); | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 248 |  | 
|  | 249 | } else { // Parent process | 
|  | 250 | // Close the unused pipe write end | 
|  | 251 | close(pipe_fd[1]); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 252 |  | 
|  | 253 | // Free the resources | 
|  | 254 | context_.reset(NULL); | 
|  | 255 | irb_.reset(NULL); | 
|  | 256 | module_ = NULL; | 
|  | 257 |  | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 258 | // Read the result out from the pipe read end (until failure) | 
|  | 259 | const size_t buf_size = 1024; | 
|  | 260 | std::vector<uint8_t> buf(buf_size); | 
|  | 261 | while (true) { | 
|  | 262 | // Read from the pipe | 
|  | 263 | ssize_t nread = read(pipe_fd[0], &*buf.begin(), buf_size); | 
|  | 264 | if (nread < 0) { | 
|  | 265 | if (errno == EAGAIN || errno == EINTR) { | 
|  | 266 | continue; | 
|  | 267 | } else { | 
|  | 268 | LOG(ERROR) << "Unexpected error during IPC: " << strerror(errno); | 
|  | 269 | } | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | // Append to the end of the elf_image_ | 
| Logan Chien | 08e1ba3 | 2012-05-08 15:08:51 +0800 | [diff] [blame] | 273 | elf_image_.append(buf.begin(), buf.begin() + nread); | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 274 |  | 
|  | 275 | if (nread < static_cast<ssize_t>(buf_size)) { // EOF reached! | 
|  | 276 | break; | 
|  | 277 | } | 
|  | 278 | } | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 279 |  | 
| Shih-wei Liao | e8ecce7 | 2012-04-23 15:00:32 -0700 | [diff] [blame] | 280 | close(pipe_fd[0]); | 
|  | 281 |  | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 282 | // Wait for child to finish | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 283 | int status; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 284 | pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); | 
|  | 285 | if (got_pid != pid) { | 
|  | 286 | PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid; | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 287 | elf_image_.clear(); | 
| Logan Chien | b9eaeea | 2012-03-17 19:45:01 +0800 | [diff] [blame] | 288 | return false; | 
|  | 289 | } | 
|  | 290 |  | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 291 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { | 
|  | 292 | LOG(ERROR) << "Failed to compile the bitcode: " << WEXITSTATUS(status); | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 293 | elf_image_.clear(); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 294 | return false; | 
| Shih-wei Liao | 1776572 | 2012-04-17 16:42:19 -0700 | [diff] [blame] | 295 | } | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 296 |  | 
|  | 297 | LOG(INFO) << "Compilation Unit: " << elf_idx_ << " (done)"; | 
|  | 298 | return true; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 299 | } | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 300 | } | 
|  | 301 |  | 
|  | 302 |  | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 303 | void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func, | 
|  | 304 | CompiledMethod* compiled_method) { | 
| Logan Chien | 8ba2fc5 | 2012-04-23 09:10:46 +0800 | [diff] [blame] | 305 | MutexLock GUARD(cunit_lock_); | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 306 | compiled_methods_map_.Put(func, compiled_method); | 
|  | 307 | } | 
|  | 308 |  | 
|  | 309 |  | 
|  | 310 | void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func, | 
|  | 311 | size_t frame_size_in_bytes) { | 
| Logan Chien | 8ba2fc5 | 2012-04-23 09:10:46 +0800 | [diff] [blame] | 312 | MutexLock GUARD(cunit_lock_); | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 313 | SafeMap<const llvm::Function*, CompiledMethod*>::iterator iter = | 
|  | 314 | compiled_methods_map_.find(func); | 
|  | 315 |  | 
|  | 316 | if (iter != compiled_methods_map_.end()) { | 
|  | 317 | CompiledMethod* compiled_method = iter->second; | 
|  | 318 | compiled_method->SetFrameSizeInBytes(frame_size_in_bytes); | 
|  | 319 |  | 
|  | 320 | if (frame_size_in_bytes > 1728u) { | 
|  | 321 | LOG(WARNING) << "Huge frame size: " << frame_size_in_bytes | 
|  | 322 | << " elf_idx=" << compiled_method->GetElfIndex() | 
|  | 323 | << " elf_func_idx=" << compiled_method->GetElfFuncIndex(); | 
|  | 324 | } | 
|  | 325 | } | 
|  | 326 | } | 
|  | 327 |  | 
| Logan Chien | b1bab1c | 2012-05-11 11:05:45 +0800 | [diff] [blame^] | 328 | bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) { | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 329 | // Lookup the LLVM target | 
|  | 330 | char const* target_triple = NULL; | 
|  | 331 | char const* target_attr = NULL; | 
|  | 332 |  | 
| Logan Chien | b1bab1c | 2012-05-11 11:05:45 +0800 | [diff] [blame^] | 333 | switch (insn_set_) { | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 334 | case kThumb2: | 
|  | 335 | target_triple = "thumb-none-linux-gnueabi"; | 
|  | 336 | target_attr = "+thumb2,+neon,+neonfp,+vfp3"; | 
|  | 337 | break; | 
|  | 338 |  | 
|  | 339 | case kArm: | 
|  | 340 | target_triple = "armv7-none-linux-gnueabi"; | 
|  | 341 | // TODO: Fix for Xoom. | 
|  | 342 | target_attr = "+v7,+neon,+neonfp,+vfp3"; | 
|  | 343 | break; | 
|  | 344 |  | 
|  | 345 | case kX86: | 
|  | 346 | target_triple = "i386-pc-linux-gnu"; | 
|  | 347 | target_attr = ""; | 
|  | 348 | break; | 
|  | 349 |  | 
|  | 350 | case kMips: | 
|  | 351 | target_triple = "mipsel-unknown-linux"; | 
|  | 352 | target_attr = "mips32r2"; | 
|  | 353 | break; | 
|  | 354 |  | 
|  | 355 | default: | 
| Logan Chien | b1bab1c | 2012-05-11 11:05:45 +0800 | [diff] [blame^] | 356 | LOG(FATAL) << "Unknown instruction set: " << insn_set_; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 357 | } | 
|  | 358 |  | 
|  | 359 | std::string errmsg; | 
|  | 360 | llvm::Target const* target = | 
|  | 361 | llvm::TargetRegistry::lookupTarget(target_triple, errmsg); | 
|  | 362 |  | 
|  | 363 | CHECK(target != NULL) << errmsg; | 
|  | 364 |  | 
|  | 365 | // Target options | 
|  | 366 | llvm::TargetOptions target_options; | 
|  | 367 | target_options.FloatABIType = llvm::FloatABI::Soft; | 
|  | 368 | target_options.NoFramePointerElim = true; | 
|  | 369 | target_options.NoFramePointerElimNonLeaf = true; | 
|  | 370 | target_options.UseSoftFloat = false; | 
|  | 371 | target_options.EnableFastISel = true; | 
|  | 372 |  | 
|  | 373 | // Create the llvm::TargetMachine | 
| Logan Chien | b6bed0b | 2012-05-04 15:03:56 +0800 | [diff] [blame] | 374 | llvm::OwningPtr<llvm::TargetMachine> target_machine( | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 375 | target->createTargetMachine(target_triple, "", target_attr, target_options, | 
|  | 376 | llvm::Reloc::Static, llvm::CodeModel::Small, | 
| TDYa127 | e4c2ccc | 2012-05-13 21:10:36 -0700 | [diff] [blame] | 377 | llvm::CodeGenOpt::Less)); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 378 |  | 
| Logan Chien | b6bed0b | 2012-05-04 15:03:56 +0800 | [diff] [blame] | 379 | CHECK(target_machine.get() != NULL) << "Failed to create target machine"; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 380 |  | 
|  | 381 | // Add target data | 
|  | 382 | llvm::TargetData const* target_data = target_machine->getTargetData(); | 
|  | 383 |  | 
|  | 384 | // PassManager for code generation passes | 
|  | 385 | llvm::PassManager pm; | 
|  | 386 | pm.add(new llvm::TargetData(*target_data)); | 
|  | 387 |  | 
|  | 388 | // FunctionPassManager for optimization pass | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 389 | llvm::FunctionPassManager fpm(module_); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 390 | fpm.add(new llvm::TargetData(*target_data)); | 
|  | 391 |  | 
| TDYa127 | f15b0ab | 2012-05-11 21:01:36 -0700 | [diff] [blame] | 392 | if (bitcode_filename_.empty()) { | 
|  | 393 | // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the | 
|  | 394 | // regular FunctionPass. | 
|  | 395 | fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get())); | 
|  | 396 | } else { | 
|  | 397 | // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file. | 
|  | 398 | llvm::FunctionPassManager fpm2(module_); | 
|  | 399 | fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get())); | 
|  | 400 | fpm2.doInitialization(); | 
|  | 401 | for (llvm::Module::iterator F = module_->begin(), E = module_->end(); | 
|  | 402 | F != E; ++F) { | 
|  | 403 | fpm2.run(*F); | 
|  | 404 | } | 
|  | 405 | fpm2.doFinalization(); | 
|  | 406 |  | 
|  | 407 |  | 
|  | 408 | // Write bitcode to file | 
|  | 409 | std::string errmsg; | 
|  | 410 |  | 
|  | 411 | llvm::OwningPtr<llvm::tool_output_file> out_file( | 
|  | 412 | new llvm::tool_output_file(bitcode_filename_.c_str(), errmsg, | 
|  | 413 | llvm::raw_fd_ostream::F_Binary)); | 
|  | 414 |  | 
|  | 415 |  | 
|  | 416 | if (!errmsg.empty()) { | 
|  | 417 | LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; | 
|  | 418 | return false; | 
|  | 419 | } | 
|  | 420 |  | 
|  | 421 | llvm::WriteBitcodeToFile(module_, out_file->os()); | 
|  | 422 | out_file->keep(); | 
|  | 423 | } | 
|  | 424 |  | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 425 | // Add optimization pass | 
|  | 426 | llvm::PassManagerBuilder pm_builder; | 
| Shih-wei Liao | e0e4024 | 2012-05-08 01:04:03 -0700 | [diff] [blame] | 427 | //pm_builder.Inliner = llvm::createFunctionInliningPass(); | 
|  | 428 | pm_builder.Inliner = llvm::createAlwaysInlinerPass(); | 
| Shih-wei Liao | 415576b | 2012-04-23 15:28:53 -0700 | [diff] [blame] | 429 | //pm_builder.Inliner = llvm::createPartialInliningPass(); | 
|  | 430 | pm_builder.OptLevel = 3; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 431 | pm_builder.DisableSimplifyLibCalls = 1; | 
| TDYa127 | e4c2ccc | 2012-05-13 21:10:36 -0700 | [diff] [blame] | 432 | pm_builder.DisableUnitAtATime = 1; | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 433 | pm_builder.populateModulePassManager(pm); | 
|  | 434 | pm_builder.populateFunctionPassManager(fpm); | 
|  | 435 |  | 
|  | 436 | // Add passes to emit ELF image | 
|  | 437 | { | 
| Logan Chien | 08e1ba3 | 2012-05-08 15:08:51 +0800 | [diff] [blame] | 438 | llvm::formatted_raw_ostream formatted_os(out_stream, false); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 439 |  | 
|  | 440 | // Ask the target to add backend passes as necessary. | 
|  | 441 | if (target_machine->addPassesToEmitFile(pm, | 
|  | 442 | formatted_os, | 
|  | 443 | llvm::TargetMachine::CGFT_ObjectFile, | 
|  | 444 | true)) { | 
|  | 445 | LOG(FATAL) << "Unable to generate ELF for this target"; | 
|  | 446 | return false; | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | // FIXME: Unable to run the UpdateFrameSizePass pass since it tries to | 
|  | 450 | //        update the value reside in the different address space. | 
|  | 451 | // Add pass to update the frame_size_in_bytes_ | 
|  | 452 | //pm.add(new ::UpdateFrameSizePass(this)); | 
|  | 453 |  | 
|  | 454 | // Run the per-function optimization | 
|  | 455 | fpm.doInitialization(); | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 456 | for (llvm::Module::iterator F = module_->begin(), E = module_->end(); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 457 | F != E; ++F) { | 
|  | 458 | fpm.run(*F); | 
|  | 459 | } | 
|  | 460 | fpm.doFinalization(); | 
|  | 461 |  | 
|  | 462 | // Run the code generation passes | 
| Logan Chien | 799ef4f | 2012-04-23 00:17:47 +0800 | [diff] [blame] | 463 | pm.run(*module_); | 
| Shih-wei Liao | d7726e4 | 2012-04-20 15:23:36 -0700 | [diff] [blame] | 464 | } | 
|  | 465 |  | 
|  | 466 | return true; | 
|  | 467 | } | 
| Logan Chien | 110bcba | 2012-04-16 19:11:28 +0800 | [diff] [blame] | 468 |  | 
| Logan Chien | 8b977d3 | 2012-02-21 19:14:55 +0800 | [diff] [blame] | 469 | } // namespace compiler_llvm | 
|  | 470 | } // namespace art |