Home | History | Annotate | Download | only in code_gen
      1 /*
      2  * Copyright (C) 2013 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 <string>
     18 #include <llvm/PassManager.h>
     19 #include <llvm/Support/TargetRegistry.h>
     20 #include <llvm/Support/FormattedStream.h>
     21 #include <llvm/Target/TargetMachine.h>
     22 #include <llvm/Transforms/IPO.h>
     23 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
     24 
     25 #include "base/logging.h"
     26 #include "driver/compiler_driver.h"
     27 #include "sea_ir/ir/sea.h"
     28 #include "sea_ir/code_gen/code_gen.h"
     29 
     30 
     31 namespace sea_ir {
     32 std::string CodeGenData::GetElf(art::InstructionSet instruction_set) {
     33   std::string elf;
     34   ::llvm::raw_string_ostream out_stream(elf);
     35   // Lookup the LLVM target
     36   std::string target_triple;
     37   std::string target_cpu;
     38   std::string target_attr;
     39   art::CompilerDriver::InstructionSetToLLVMTarget(instruction_set,
     40       target_triple, target_cpu, target_attr);
     41 
     42   std::string errmsg;
     43   const ::llvm::Target* target =
     44     ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
     45 
     46   CHECK(target != NULL) << errmsg;
     47 
     48   // Target options
     49   ::llvm::TargetOptions target_options;
     50   target_options.FloatABIType = ::llvm::FloatABI::Soft;
     51   target_options.NoFramePointerElim = true;
     52   target_options.NoFramePointerElimNonLeaf = true;
     53   target_options.UseSoftFloat = false;
     54   target_options.EnableFastISel = false;
     55 
     56   // Create the ::llvm::TargetMachine
     57   ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine(
     58     target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
     59                                 ::llvm::Reloc::Static, ::llvm::CodeModel::Small,
     60                                 ::llvm::CodeGenOpt::Aggressive));
     61 
     62   CHECK(target_machine.get() != NULL) << "Failed to create target machine";
     63 
     64   // Add target data
     65   const ::llvm::DataLayout* data_layout = target_machine->getDataLayout();
     66 
     67   // PassManager for code generation passes
     68   ::llvm::PassManager pm;
     69   pm.add(new ::llvm::DataLayout(*data_layout));
     70 
     71   // FunctionPassManager for optimization pass
     72   ::llvm::FunctionPassManager fpm(&module_);
     73   fpm.add(new ::llvm::DataLayout(*data_layout));
     74 
     75   // Add optimization pass
     76   ::llvm::PassManagerBuilder pm_builder;
     77   // TODO: Use inliner after we can do IPO.
     78   pm_builder.Inliner = NULL;
     79   // pm_builder.Inliner = ::llvm::createFunctionInliningPass();
     80   // pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
     81   // pm_builder.Inliner = ::llvm::createPartialInliningPass();
     82   pm_builder.OptLevel = 3;
     83   pm_builder.DisableSimplifyLibCalls = 1;
     84   pm_builder.DisableUnitAtATime = 1;
     85   pm_builder.populateFunctionPassManager(fpm);
     86   pm_builder.populateModulePassManager(pm);
     87   pm.add(::llvm::createStripDeadPrototypesPass());
     88   // Add passes to emit ELF image
     89   {
     90     ::llvm::formatted_raw_ostream formatted_os(out_stream, false);
     91     // Ask the target to add backend passes as necessary.
     92     if (target_machine->addPassesToEmitFile(pm,
     93                                             formatted_os,
     94                                             ::llvm::TargetMachine::CGFT_ObjectFile,
     95                                             true)) {
     96       LOG(FATAL) << "Unable to generate ELF for this target";
     97     }
     98 
     99     // Run the code generation passes
    100     pm.run(module_);
    101   }
    102   return elf;
    103 }
    104 }  // namespace sea_ir
    105