Files
archived-llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Tim Northover 5ae8ffe436 GlobalISel: freeze reserved regs after IRTranslator.
We can freeze the registers after the MachineFrameInfo has been configured (by
telling it about calls, inline asm, ...). This doesn't happen at all yet, but
will be part of IR translation.

Fixes -verify-machineinstrs assertion.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275221 91177308-0d34-0410-b5e6-96231b3b80d8
2016-07-12 22:23:42 +00:00

165 lines
5.4 KiB
C++

//===-- 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;
}