diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp')
-rw-r--r-- | contrib/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/contrib/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/contrib/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp new file mode 100644 index 0000000..b8a960c --- /dev/null +++ b/contrib/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -0,0 +1,164 @@ +//===-- llvm/CodeGen/GlobalISel/IRTranslator.cpp - IRTranslator --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file implements the IRTranslator class. +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GlobalISel/IRTranslator.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/Target/TargetLowering.h" + +#define DEBUG_TYPE "irtranslator" + +using namespace llvm; + +char IRTranslator::ID = 0; +INITIALIZE_PASS(IRTranslator, "irtranslator", "IRTranslator LLVM IR -> MI", + false, false); + +IRTranslator::IRTranslator() : MachineFunctionPass(ID), MRI(nullptr) { + initializeIRTranslatorPass(*PassRegistry::getPassRegistry()); +} + +unsigned IRTranslator::getOrCreateVReg(const Value &Val) { + unsigned &ValReg = ValToVReg[&Val]; + // Check if this is the first time we see Val. + if (!ValReg) { + // Fill ValRegsSequence with the sequence of registers + // we need to concat together to produce the value. + assert(Val.getType()->isSized() && + "Don't know how to create an empty vreg"); + assert(!Val.getType()->isAggregateType() && "Not yet implemented"); + unsigned Size = Val.getType()->getPrimitiveSizeInBits(); + unsigned VReg = MRI->createGenericVirtualRegister(Size); + ValReg = VReg; + assert(!isa<Constant>(Val) && "Not yet implemented"); + } + return ValReg; +} + +MachineBasicBlock &IRTranslator::getOrCreateBB(const BasicBlock &BB) { + MachineBasicBlock *&MBB = BBToMBB[&BB]; + if (!MBB) { + MachineFunction &MF = MIRBuilder.getMF(); + MBB = MF.CreateMachineBasicBlock(); + MF.push_back(MBB); + } + return *MBB; +} + +bool IRTranslator::translateBinaryOp(unsigned Opcode, const Instruction &Inst) { + // Get or create a virtual register for each value. + // Unless the value is a Constant => loadimm cst? + // or inline constant each time? + // Creation of a virtual register needs to have a size. + unsigned Op0 = getOrCreateVReg(*Inst.getOperand(0)); + unsigned Op1 = getOrCreateVReg(*Inst.getOperand(1)); + unsigned Res = getOrCreateVReg(Inst); + MIRBuilder.buildInstr(Opcode, Inst.getType(), Res, Op0, Op1); + return true; +} + +bool IRTranslator::translateReturn(const Instruction &Inst) { + assert(isa<ReturnInst>(Inst) && "Return expected"); + const Value *Ret = cast<ReturnInst>(Inst).getReturnValue(); + // The target may mess up with the insertion point, but + // this is not important as a return is the last instruction + // of the block anyway. + return CLI->lowerReturn(MIRBuilder, Ret, !Ret ? 0 : getOrCreateVReg(*Ret)); +} + +bool IRTranslator::translateBr(const Instruction &Inst) { + assert(isa<BranchInst>(Inst) && "Branch expected"); + const BranchInst &BrInst = *cast<BranchInst>(&Inst); + if (BrInst.isUnconditional()) { + const BasicBlock &BrTgt = *cast<BasicBlock>(BrInst.getOperand(0)); + MachineBasicBlock &TgtBB = getOrCreateBB(BrTgt); + MIRBuilder.buildInstr(TargetOpcode::G_BR, BrTgt.getType(), TgtBB); + } else { + assert(0 && "Not yet implemented"); + } + // Link successors. + MachineBasicBlock &CurBB = MIRBuilder.getMBB(); + for (const BasicBlock *Succ : BrInst.successors()) + CurBB.addSuccessor(&getOrCreateBB(*Succ)); + return true; +} + +bool IRTranslator::translate(const Instruction &Inst) { + MIRBuilder.setDebugLoc(Inst.getDebugLoc()); + switch(Inst.getOpcode()) { + case Instruction::Add: + return translateBinaryOp(TargetOpcode::G_ADD, Inst); + case Instruction::Or: + return translateBinaryOp(TargetOpcode::G_OR, Inst); + case Instruction::Br: + return translateBr(Inst); + case Instruction::Ret: + return translateReturn(Inst); + + default: + llvm_unreachable("Opcode not supported"); + } +} + + +void IRTranslator::finalize() { + // Release the memory used by the different maps we + // needed during the translation. + ValToVReg.clear(); + Constants.clear(); +} + +bool IRTranslator::runOnMachineFunction(MachineFunction &MF) { + const Function &F = *MF.getFunction(); + if (F.empty()) + return false; + CLI = MF.getSubtarget().getCallLowering(); + MIRBuilder.setMF(MF); + MRI = &MF.getRegInfo(); + // Setup the arguments. + MachineBasicBlock &MBB = getOrCreateBB(F.front()); + MIRBuilder.setMBB(MBB); + SmallVector<unsigned, 8> VRegArgs; + for (const Argument &Arg: F.args()) + VRegArgs.push_back(getOrCreateVReg(Arg)); + bool Succeeded = + CLI->lowerFormalArguments(MIRBuilder, F.getArgumentList(), VRegArgs); + if (!Succeeded) + report_fatal_error("Unable to lower arguments"); + + for (const BasicBlock &BB: F) { + MachineBasicBlock &MBB = getOrCreateBB(BB); + // Set the insertion point of all the following translations to + // the end of this basic block. + MIRBuilder.setMBB(MBB); + for (const Instruction &Inst: BB) { + bool Succeeded = translate(Inst); + if (!Succeeded) { + DEBUG(dbgs() << "Cannot translate: " << Inst << '\n'); + report_fatal_error("Unable to translate instruction"); + } + } + } + + // Now that the MachineFrameInfo has been configured, no further changes to + // the reserved registers are possible. + MRI->freezeReservedRegs(MF); + + return false; +} |