summaryrefslogtreecommitdiffstats
path: root/compiler/sea_ir/code_gen
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/sea_ir/code_gen')
-rw-r--r--compiler/sea_ir/code_gen/code_gen.cc291
-rw-r--r--compiler/sea_ir/code_gen/code_gen.h171
-rw-r--r--compiler/sea_ir/code_gen/code_gen_data.cc104
3 files changed, 0 insertions, 566 deletions
diff --git a/compiler/sea_ir/code_gen/code_gen.cc b/compiler/sea_ir/code_gen/code_gen.cc
deleted file mode 100644
index 8d79c41545..0000000000
--- a/compiler/sea_ir/code_gen/code_gen.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <llvm/Support/raw_ostream.h>
-
-#include "base/logging.h"
-#include "utils.h"
-
-#include "sea_ir/ir/sea.h"
-#include "sea_ir/code_gen/code_gen.h"
-#include "sea_ir/types/type_inference.h"
-#include "sea_ir/types/types.h"
-
-namespace sea_ir {
-
-void CodeGenPrepassVisitor::Visit(PhiInstructionNode* phi) {
- Region* r = phi->GetRegion();
- const std::vector<Region*>* predecessors = r->GetPredecessors();
- DCHECK(NULL != predecessors);
- DCHECK_GT(predecessors->size(), 0u);
- llvm::PHINode *llvm_phi = llvm_data_->builder_.CreatePHI(
- llvm::Type::getInt32Ty(*llvm_data_->context_), predecessors->size(), phi->StringId());
- llvm_data_->AddValue(phi, llvm_phi);
-}
-
-void CodeGenPassVisitor::Initialize(SeaGraph* graph) {
- Region* root_region;
- ordered_regions_.clear();
- for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
- cit != graph->GetRegions()->end(); cit++ ) {
- if ((*cit)->GetIDominator() == (*cit)) {
- root_region = *cit;
- }
- }
- ordered_regions_.push_back(root_region);
- for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
- Region* current_region = ordered_regions_.at(id);
- const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
- for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
- cit != dominated_regions->end(); cit++ ) {
- ordered_regions_.push_back(*cit);
- }
- }
-}
-
-void CodeGenPostpassVisitor::Visit(SeaGraph* graph) { }
-void CodeGenVisitor::Visit(SeaGraph* graph) { }
-void CodeGenPrepassVisitor::Visit(SeaGraph* graph) {
- std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
- // TODO: It may be better to extract correct types from dex
- // instead than from type inference.
- DCHECK(parameters != NULL);
- std::vector<llvm::Type*> parameter_types;
- for (std::vector<SignatureNode*>::const_iterator param_iterator = parameters->begin();
- param_iterator!= parameters->end(); param_iterator++) {
- const Type* param_type = graph->ti_->type_data_.FindTypeOf((*param_iterator)->Id());
- DCHECK(param_type->Equals(graph->ti_->type_cache_->Integer()))
- << "Code generation for types other than integer not implemented.";
- parameter_types.push_back(llvm::Type::getInt32Ty(*llvm_data_->context_));
- }
-
- // TODO: Get correct function return type.
- const Type* return_type = graph->ti_->type_data_.FindTypeOf(-1);
- DCHECK(return_type->Equals(graph->ti_->type_cache_->Integer()))
- << "Code generation for types other than integer not implemented.";
- llvm::FunctionType *function_type = llvm::FunctionType::get(
- llvm::Type::getInt32Ty(*llvm_data_->context_),
- parameter_types, false);
-
- llvm_data_->function_ = llvm::Function::Create(function_type,
- llvm::Function::ExternalLinkage, function_name_, &llvm_data_->module_);
- unsigned param_id = 0;
- for (llvm::Function::arg_iterator arg_it = llvm_data_->function_->arg_begin();
- param_id != llvm_data_->function_->arg_size(); ++arg_it, ++param_id) {
- // TODO: The "+1" is because of the Method parameter on position 0.
- DCHECK(parameters->size() > param_id) << "Insufficient parameters for function signature";
- // Build parameter register name for LLVM IR clarity.
- std::string arg_name = art::StringPrintf("r%d", parameters->at(param_id)->GetResultRegister());
- arg_it->setName(arg_name);
- SignatureNode* parameter = parameters->at(param_id);
- llvm_data_->AddValue(parameter, arg_it);
- }
-
- std::vector<Region*>* regions = &ordered_regions_;
- DCHECK_GT(regions->size(), 0u);
- // Then create all other basic blocks.
- for (std::vector<Region*>::const_iterator cit = regions->begin(); cit != regions->end(); cit++) {
- llvm::BasicBlock* new_basic_block = llvm::BasicBlock::Create(*llvm_data_->context_,
- (*cit)->StringId(), llvm_data_->function_);
- llvm_data_->AddBlock((*cit), new_basic_block);
- }
-}
-
-void CodeGenPrepassVisitor::Visit(Region* region) {
- llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
-}
-void CodeGenPostpassVisitor::Visit(Region* region) {
- llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
-}
-void CodeGenVisitor::Visit(Region* region) {
- llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
-}
-
-
-void CodeGenVisitor::Visit(InstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- DCHECK(0); // This whole function is useful only during development.
-}
-
-void CodeGenVisitor::Visit(UnnamedConstInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "1.Instruction: " << instr << std::endl;
- llvm_data_->AddValue(instruction,
- llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
-}
-
-void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "1.Instruction: " << instr << std::endl;
- llvm_data_->AddValue(instruction,
- llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
-}
-void CodeGenVisitor::Visit(ReturnInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "2.Instruction: " << instr << std::endl;
- DCHECK_GT(instruction->GetSSAProducers().size(), 0u);
- llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAProducers().at(0));
- llvm_data_->builder_.CreateRet(return_value);
-}
-void CodeGenVisitor::Visit(IfNeInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "3.Instruction: " << instr << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
- DCHECK_GT(ssa_uses.size(), 1u);
- InstructionNode* use_l = ssa_uses.at(0);
- llvm::Value* left = llvm_data_->GetValue(use_l);
-
- InstructionNode* use_r = ssa_uses.at(1);
- llvm::Value* right = llvm_data_->GetValue(use_r);
- llvm::Value* ifne = llvm_data_->builder_.CreateICmpNE(left, right, instruction->StringId());
- DCHECK(instruction->GetRegion() != NULL);
- std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
- DCHECK_GT(successors->size(), 0u);
- llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
- llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
-
- llvm_data_->builder_.CreateCondBr(ifne, then_block, else_block);
-}
-
-/*
-void CodeGenVisitor::Visit(AddIntLitInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "4.Instruction: " << instr << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
- InstructionNode* use_l = ssa_uses.at(0);
- llvm::Value* left = llvm_data->GetValue(use_l);
- llvm::Value* right = llvm::ConstantInt::get(*llvm_data->context_,
- llvm::APInt(32, instruction->GetConstValue()));
- llvm::Value* result = llvm_data->builder_.CreateAdd(left, right);
- llvm_data->AddValue(instruction, result);
-}
-*/
-void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "5.Instruction: " << instr << std::endl;
- // TODO: Currently, this "mov" instruction is simulated by "res = return_register + 0".
- // This is inefficient, but should be optimized out by the coalescing phase of the reg alloc.
- // The TODO is to either ensure that this happens, or to
- // remove the move-result instructions completely from the IR
- // by merging them with the invoke-* instructions,
- // since their purpose of minimizing the number of opcodes in dex is
- // not relevant for the IR. (Will need to have different
- // instruction subclasses for functions and procedures.)
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
- InstructionNode* use_l = ssa_uses.at(0);
- llvm::Value* left = llvm_data_->GetValue(use_l);
- llvm::Value* right = llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0));
- llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
- llvm_data_->AddValue(instruction, result);
-}
-void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
- std::string instr = invoke->GetInstruction()->DumpString(NULL);
- std::cout << "6.Instruction: " << instr << std::endl;
- // TODO: Build callee LLVM function name.
- std::string symbol = "dex_";
- symbol += art::MangleForJni(PrettyMethod(invoke->GetCalledMethodIndex(), dex_file_));
- std::string function_name = "dex_int_00020Main_fibonacci_00028int_00029";
- llvm::Function *callee = llvm_data_->module_.getFunction(function_name);
- // TODO: Add proper checking of the matching between formal and actual signature.
- DCHECK(NULL != callee);
- std::vector<llvm::Value*> parameter_values;
- std::vector<InstructionNode*> parameter_sources = invoke->GetSSAProducers();
- // TODO: Replace first parameter with Method argument instead of 0.
- parameter_values.push_back(llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0)));
- for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin();
- cit != parameter_sources.end(); ++cit) {
- llvm::Value* parameter_value = llvm_data_->GetValue((*cit));
- DCHECK(NULL != parameter_value);
- parameter_values.push_back(parameter_value);
- }
- llvm::Value* return_value = llvm_data_->builder_.CreateCall(callee,
- parameter_values, invoke->StringId());
- llvm_data_->AddValue(invoke, return_value);
-}
-void CodeGenVisitor::Visit(AddIntInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "7.Instruction: " << instr << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
- DCHECK_GT(ssa_uses.size(), 1u);
- InstructionNode* use_l = ssa_uses.at(0);
- InstructionNode* use_r = ssa_uses.at(1);
- llvm::Value* left = llvm_data_->GetValue(use_l);
- llvm::Value* right = llvm_data_->GetValue(use_r);
- llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
- llvm_data_->AddValue(instruction, result);
-}
-void CodeGenVisitor::Visit(GotoInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "8.Instruction: " << instr << std::endl;
- std::vector<sea_ir::Region*>* targets = instruction->GetRegion()->GetSuccessors();
- DCHECK_EQ(targets->size(), 1u);
- llvm::BasicBlock* target_block = llvm_data_->GetBlock(targets->at(0));
- llvm_data_->builder_.CreateBr(target_block);
-}
-void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) {
- std::string instr = instruction->GetInstruction()->DumpString(NULL);
- std::cout << "9. Instruction: " << instr << "; Id: " <<instruction << std::endl;
- std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
- DCHECK_GT(ssa_uses.size(), 0u);
- InstructionNode* use_l = ssa_uses.at(0);
- llvm::Value* left = llvm_data_->GetValue(use_l);
- llvm::Value* ifeqz = llvm_data_->builder_.CreateICmpEQ(left,
- llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt::getNullValue(32)),
- instruction->StringId());
- DCHECK(instruction->GetRegion() != NULL);
- std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
- DCHECK_GT(successors->size(), 0u);
- llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
- llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
- llvm_data_->builder_.CreateCondBr(ifeqz, then_block, else_block);
-}
-
-void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) {
- std::cout << "10. Instruction: Phi(" << phi->GetRegisterNumber() << ")" << std::endl;
- Region* r = phi->GetRegion();
- const std::vector<Region*>* predecessors = r->GetPredecessors();
- DCHECK(NULL != predecessors);
- DCHECK_GT(predecessors->size(), 0u);
- // Prepass (CodeGenPrepassVisitor) should create the phi function value.
- llvm::PHINode* llvm_phi = (llvm::PHINode*) llvm_data_->GetValue(phi);
- int predecessor_pos = 0;
- for (std::vector<Region*>::const_iterator cit = predecessors->begin();
- cit != predecessors->end(); ++cit) {
- std::vector<InstructionNode*>* defining_instructions = phi->GetSSAUses(predecessor_pos++);
- DCHECK_EQ(defining_instructions->size(), 1u);
- InstructionNode* defining_instruction = defining_instructions->at(0);
- DCHECK(NULL != defining_instruction);
- Region* incoming_region = *cit;
- llvm::BasicBlock* incoming_basic_block = llvm_data_->GetBlock(incoming_region);
- llvm::Value* incoming_value = llvm_data_->GetValue(defining_instruction);
- llvm_phi->addIncoming(incoming_value, incoming_basic_block);
- }
-}
-
-void CodeGenVisitor::Visit(SignatureNode* signature) {
- DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
- "Signature nodes must correspond to a single parameter register.";
-}
-void CodeGenPrepassVisitor::Visit(SignatureNode* signature) {
- DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
- "Signature nodes must correspond to a single parameter register.";
-}
-void CodeGenPostpassVisitor::Visit(SignatureNode* signature) {
- DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
- "Signature nodes must correspond to a single parameter register.";
-}
-
-} // namespace sea_ir
diff --git a/compiler/sea_ir/code_gen/code_gen.h b/compiler/sea_ir/code_gen/code_gen.h
deleted file mode 100644
index 544e9f0650..0000000000
--- a/compiler/sea_ir/code_gen/code_gen.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
-#define ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
-
-#include "instruction_set.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Analysis/Verifier.h"
-#include "sea_ir/ir/visitor.h"
-
-namespace sea_ir {
-// Abstracts away the containers we use to map SEA IR objects to LLVM IR objects.
-class CodeGenData {
- public:
- explicit CodeGenData(): context_(&llvm::getGlobalContext()), module_("sea_ir", *context_),
- builder_(*context_), function_(), blocks_(), values_() { }
- // Returns the llvm::BasicBlock* corresponding to the sea_ir::Region with id @region_id.
- llvm::BasicBlock* GetBlock(int region_id) {
- std::map<int, llvm::BasicBlock*>::iterator block_it = blocks_.find(region_id);
- DCHECK(block_it != blocks_.end());
- return block_it->second;
- }
- // Returns the llvm::BasicBlock* corresponding top the sea_ir::Region @region.
- llvm::BasicBlock* GetBlock(Region* region) {
- return GetBlock(region->Id());
- }
- // Records @block as corresponding to the sea_ir::Region with id @region_id.
- void AddBlock(int region_id, llvm::BasicBlock* block) {
- blocks_.insert(std::pair<int, llvm::BasicBlock*>(region_id, block));
- }
- // Records @block as corresponding to the sea_ir::Region with @region.
- void AddBlock(Region* region, llvm::BasicBlock* block) {
- AddBlock(region->Id(), block);
- }
-
- llvm::Value* GetValue(int instruction_id) {
- std::map<int, llvm::Value*>::iterator value_it = values_.find(instruction_id);
- DCHECK(value_it != values_.end());
- return value_it->second;
- }
- // Returns the llvm::Value* corresponding to the output of @instruction.
- llvm::Value* GetValue(InstructionNode* instruction) {
- return GetValue(instruction->Id());
- }
- // Records @value as corresponding to the sea_ir::InstructionNode with id @instruction_id.
- void AddValue(int instruction_id, llvm::Value* value) {
- values_.insert(std::pair<int, llvm::Value*>(instruction_id, value));
- }
- // Records @value as corresponding to the sea_ir::InstructionNode @instruction.
- void AddValue(InstructionNode* instruction, llvm::Value* value) {
- AddValue(instruction->Id(), value);
- }
- // Generates and returns in @elf the executable code corresponding to the llvm module
- //
- std::string GetElf(art::InstructionSet instruction_set);
-
- llvm::LLVMContext* const context_;
- llvm::Module module_;
- llvm::IRBuilder<> builder_;
- llvm::Function* function_;
-
- private:
- std::map<int, llvm::BasicBlock*> blocks_;
- std::map<int, llvm::Value*> values_;
-};
-
-class CodeGenPassVisitor: public IRVisitor {
- public:
- explicit CodeGenPassVisitor(CodeGenData* cgd): llvm_data_(cgd) { }
- CodeGenPassVisitor(): llvm_data_(new CodeGenData()) { }
- // Initialize any data structure needed before the start of visiting.
- virtual void Initialize(SeaGraph* graph);
- CodeGenData* GetData() {
- return llvm_data_;
- }
- void Write(std::string file) {
- llvm_data_->module_.dump();
- llvm::verifyFunction(*llvm_data_->function_);
- }
-
- protected:
- CodeGenData* const llvm_data_;
-};
-
-class CodeGenPrepassVisitor: public CodeGenPassVisitor {
- public:
- explicit CodeGenPrepassVisitor(const std::string& function_name):
- function_name_(function_name) { }
- void Visit(SeaGraph* graph);
- void Visit(SignatureNode* region);
- void Visit(Region* region);
- void Visit(InstructionNode* instruction) { }
-
- void Visit(UnnamedConstInstructionNode* instruction) { }
- void Visit(ConstInstructionNode* instruction) { }
- void Visit(ReturnInstructionNode* instruction) { }
- void Visit(IfNeInstructionNode* instruction) { }
- // void Visit(AddIntLitInstructionNode* instruction) { }
- void Visit(MoveResultInstructionNode* instruction) { }
- void Visit(InvokeStaticInstructionNode* instruction) { }
- void Visit(AddIntInstructionNode* instruction) { }
- void Visit(GotoInstructionNode* instruction) { }
- void Visit(IfEqzInstructionNode* instruction) { }
- void Visit(PhiInstructionNode* region);
-
- private:
- std::string function_name_;
-};
-
-class CodeGenPostpassVisitor: public CodeGenPassVisitor {
- public:
- explicit CodeGenPostpassVisitor(CodeGenData* code_gen_data): CodeGenPassVisitor(code_gen_data) { }
- void Visit(SeaGraph* graph);
- void Visit(SignatureNode* region);
- void Visit(Region* region);
- void Visit(InstructionNode* region) { }
- void Visit(UnnamedConstInstructionNode* instruction) { }
- void Visit(ConstInstructionNode* instruction) { }
- void Visit(ReturnInstructionNode* instruction) { }
- void Visit(IfNeInstructionNode* instruction) { }
- // void Visit(AddIntLitInstructionNode* instruction) { }
- void Visit(MoveResultInstructionNode* instruction) { }
- void Visit(InvokeStaticInstructionNode* instruction) { }
- void Visit(AddIntInstructionNode* instruction) { }
- void Visit(GotoInstructionNode* instruction) { }
- void Visit(IfEqzInstructionNode* instruction) { }
- void Visit(PhiInstructionNode* region);
-};
-
-class CodeGenVisitor: public CodeGenPassVisitor {
- public:
- explicit CodeGenVisitor(CodeGenData* code_gen_data,
- const art::DexFile& dex_file): CodeGenPassVisitor(code_gen_data), dex_file_(dex_file) { }
- void Visit(SeaGraph* graph);
- void Visit(SignatureNode* region);
- void Visit(Region* region);
- void Visit(InstructionNode* region);
- void Visit(UnnamedConstInstructionNode* instruction);
- void Visit(ConstInstructionNode* instruction);
- void Visit(ReturnInstructionNode* instruction);
- void Visit(IfNeInstructionNode* instruction);
- void Visit(MoveResultInstructionNode* instruction);
- void Visit(InvokeStaticInstructionNode* instruction);
- void Visit(AddIntInstructionNode* instruction);
- void Visit(GotoInstructionNode* instruction);
- void Visit(IfEqzInstructionNode* instruction);
- void Visit(PhiInstructionNode* region) { }
-
- private:
- std::string function_name_;
- const art::DexFile& dex_file_;
-};
-} // namespace sea_ir
-#endif // ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
diff --git a/compiler/sea_ir/code_gen/code_gen_data.cc b/compiler/sea_ir/code_gen/code_gen_data.cc
deleted file mode 100644
index 17f64db70c..0000000000
--- a/compiler/sea_ir/code_gen/code_gen_data.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-#include <llvm/PassManager.h>
-#include <llvm/Support/TargetRegistry.h>
-#include <llvm/Support/FormattedStream.h>
-#include <llvm/Target/TargetMachine.h>
-#include <llvm/Transforms/IPO.h>
-#include <llvm/Transforms/IPO/PassManagerBuilder.h>
-
-#include "base/logging.h"
-#include "driver/compiler_driver.h"
-#include "sea_ir/ir/sea.h"
-#include "sea_ir/code_gen/code_gen.h"
-
-
-namespace sea_ir {
-std::string CodeGenData::GetElf(art::InstructionSet instruction_set) {
- std::string elf;
- ::llvm::raw_string_ostream out_stream(elf);
- // Lookup the LLVM target
- std::string target_triple;
- std::string target_cpu;
- std::string target_attr;
- art::CompilerDriver::InstructionSetToLLVMTarget(instruction_set,
- target_triple, target_cpu, target_attr);
-
- std::string errmsg;
- const ::llvm::Target* target =
- ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
-
- CHECK(target != NULL) << errmsg;
-
- // Target options
- ::llvm::TargetOptions target_options;
- target_options.FloatABIType = ::llvm::FloatABI::Soft;
- target_options.NoFramePointerElim = true;
- target_options.NoFramePointerElimNonLeaf = true;
- target_options.UseSoftFloat = false;
- target_options.EnableFastISel = false;
-
- // Create the ::llvm::TargetMachine
- ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine(
- target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
- ::llvm::Reloc::Static, ::llvm::CodeModel::Small,
- ::llvm::CodeGenOpt::Aggressive));
-
- CHECK(target_machine.get() != NULL) << "Failed to create target machine";
-
- // Add target data
- const ::llvm::DataLayout* data_layout = target_machine->getDataLayout();
-
- // PassManager for code generation passes
- ::llvm::PassManager pm;
- pm.add(new ::llvm::DataLayout(*data_layout));
-
- // FunctionPassManager for optimization pass
- ::llvm::FunctionPassManager fpm(&module_);
- fpm.add(new ::llvm::DataLayout(*data_layout));
-
- // Add optimization pass
- ::llvm::PassManagerBuilder pm_builder;
- // TODO: Use inliner after we can do IPO.
- pm_builder.Inliner = NULL;
- // pm_builder.Inliner = ::llvm::createFunctionInliningPass();
- // pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
- // pm_builder.Inliner = ::llvm::createPartialInliningPass();
- pm_builder.OptLevel = 3;
- pm_builder.DisableSimplifyLibCalls = 1;
- pm_builder.DisableUnitAtATime = 1;
- pm_builder.populateFunctionPassManager(fpm);
- pm_builder.populateModulePassManager(pm);
- pm.add(::llvm::createStripDeadPrototypesPass());
- // Add passes to emit ELF image
- {
- ::llvm::formatted_raw_ostream formatted_os(out_stream, false);
- // Ask the target to add backend passes as necessary.
- if (target_machine->addPassesToEmitFile(pm,
- formatted_os,
- ::llvm::TargetMachine::CGFT_ObjectFile,
- true)) {
- LOG(FATAL) << "Unable to generate ELF for this target";
- }
-
- // Run the code generation passes
- pm.run(module_);
- }
- return elf;
-}
-} // namespace sea_ir