#ifndef LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
#define LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Types.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/Allocator.h"
#include "llvm/IR/Intrinsics.h"
#include <memory>
#include <utility>
namespace llvm {
class AllocaInst;
class BasicBlock;
class CallInst;
class CallLowering;
class Constant;
class DataLayout;
class Instruction;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class MachineRegisterInfo;
class OptimizationRemarkEmitter;
class PHINode;
class TargetPassConfig;
class User;
class Value;
class IRTranslator : public MachineFunctionPass {
public:
static char ID;
private:
const CallLowering *CLI;
class ValueToVRegInfo {
public:
ValueToVRegInfo() = default;
using VRegListT = SmallVector<unsigned, 1>;
using OffsetListT = SmallVector<uint64_t, 1>;
using const_vreg_iterator =
DenseMap<const Value *, VRegListT *>::const_iterator;
using const_offset_iterator =
DenseMap<const Value *, OffsetListT *>::const_iterator;
inline const_vreg_iterator vregs_end() const { return ValToVRegs.end(); }
VRegListT *getVRegs(const Value &V) {
auto It = ValToVRegs.find(&V);
if (It != ValToVRegs.end())
return It->second;
return insertVRegs(V);
}
OffsetListT *getOffsets(const Value &V) {
auto It = TypeToOffsets.find(V.getType());
if (It != TypeToOffsets.end())
return It->second;
return insertOffsets(V);
}
const_vreg_iterator findVRegs(const Value &V) const {
return ValToVRegs.find(&V);
}
bool contains(const Value &V) const {
return ValToVRegs.find(&V) != ValToVRegs.end();
}
void reset() {
ValToVRegs.clear();
TypeToOffsets.clear();
VRegAlloc.DestroyAll();
OffsetAlloc.DestroyAll();
}
private:
VRegListT *insertVRegs(const Value &V) {
assert(ValToVRegs.find(&V) == ValToVRegs.end() && "Value already exists");
auto *VRegList = new (VRegAlloc.Allocate()) VRegListT();
ValToVRegs[&V] = VRegList;
return VRegList;
}
OffsetListT *insertOffsets(const Value &V) {
assert(TypeToOffsets.find(V.getType()) == TypeToOffsets.end() &&
"Type already exists");
auto *OffsetList = new (OffsetAlloc.Allocate()) OffsetListT();
TypeToOffsets[V.getType()] = OffsetList;
return OffsetList;
}
SpecificBumpPtrAllocator<VRegListT> VRegAlloc;
SpecificBumpPtrAllocator<OffsetListT> OffsetAlloc;
DenseMap<const Value *, VRegListT*> ValToVRegs;
DenseMap<const Type *, OffsetListT*> TypeToOffsets;
};
ValueToVRegInfo VMap;
DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB;
using CFGEdge = std::pair<const BasicBlock *, const BasicBlock *>;
DenseMap<CFGEdge, SmallVector<MachineBasicBlock *, 1>> MachinePreds;
SmallVector<std::pair<const PHINode *, SmallVector<MachineInstr *, 1>>, 4>
PendingPHIs;
DenseMap<const AllocaInst *, int> FrameIndices;
bool translate(const Instruction &Inst);
bool translate(const Constant &C, unsigned Reg);
bool translateBitCast(const User &U, MachineIRBuilder &MIRBuilder);
bool translateLoad(const User &U, MachineIRBuilder &MIRBuilder);
bool translateStore(const User &U, MachineIRBuilder &MIRBuilder);
bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
unsigned ID);
void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder);
bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op,
MachineIRBuilder &MIRBuilder);
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MachineIRBuilder &MIRBuilder);
bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder);
unsigned packRegs(const Value &V, MachineIRBuilder &MIRBuilder);
void unpackRegs(const Value &V, unsigned Src, MachineIRBuilder &MIRBuilder);
bool valueIsSplit(const Value &V,
SmallVectorImpl<uint64_t> *Offsets = nullptr);
bool translateCall(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder);
bool translateLandingPad(const User &U, MachineIRBuilder &MIRBuilder);
bool translateCast(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder);
bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder);
bool translateCompare(const User &U, MachineIRBuilder &MIRBuilder);
bool translateICmp(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCompare(U, MIRBuilder);
}
bool translateFCmp(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCompare(U, MIRBuilder);
}
void finishPendingPhis();
bool translateBinaryOp(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder);
bool translateBr(const User &U, MachineIRBuilder &MIRBuilder);
bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder);
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder);
bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder);
bool translateSelect(const User &U, MachineIRBuilder &MIRBuilder);
bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder);
bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder);
bool translateRet(const User &U, MachineIRBuilder &MIRBuilder);
bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder);
bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder);
}
bool translateSub(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SUB, U, MIRBuilder);
}
bool translateAnd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_AND, U, MIRBuilder);
}
bool translateMul(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_MUL, U, MIRBuilder);
}
bool translateOr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_OR, U, MIRBuilder);
}
bool translateXor(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_XOR, U, MIRBuilder);
}
bool translateUDiv(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_UDIV, U, MIRBuilder);
}
bool translateSDiv(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SDIV, U, MIRBuilder);
}
bool translateURem(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_UREM, U, MIRBuilder);
}
bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder);
}
bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder);
}
bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder);
}
bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder);
}
bool translateFPTrunc(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_FPTRUNC, U, MIRBuilder);
}
bool translateFPExt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_FPEXT, U, MIRBuilder);
}
bool translateFPToUI(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_FPTOUI, U, MIRBuilder);
}
bool translateFPToSI(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_FPTOSI, U, MIRBuilder);
}
bool translateUIToFP(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_UITOFP, U, MIRBuilder);
}
bool translateSIToFP(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_SITOFP, U, MIRBuilder);
}
bool translateUnreachable(const User &U, MachineIRBuilder &MIRBuilder) {
return true;
}
bool translateSExt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_SEXT, U, MIRBuilder);
}
bool translateZExt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_ZEXT, U, MIRBuilder);
}
bool translateShl(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SHL, U, MIRBuilder);
}
bool translateLShr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_LSHR, U, MIRBuilder);
}
bool translateAShr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_ASHR, U, MIRBuilder);
}
bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder);
}
bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder);
}
bool translateFDiv(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FDIV, U, MIRBuilder);
}
bool translateFRem(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder);
}
bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder);
bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder);
bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder);
bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder);
bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder);
bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateCleanupRet(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateCatchRet(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateCatchSwitch(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateFence(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder);
}
bool translateCleanupPad(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateCatchPad(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateUserOp1(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
MachineIRBuilder CurBuilder;
MachineIRBuilder EntryBuilder;
MachineFunction *MF;
MachineRegisterInfo *MRI = nullptr;
const DataLayout *DL;
const TargetPassConfig *TPC;
std::unique_ptr<OptimizationRemarkEmitter> ORE;
void finalizeFunction();
ArrayRef<unsigned> getOrCreateVRegs(const Value &Val);
unsigned getOrCreateVReg(const Value &Val) {
auto Regs = getOrCreateVRegs(Val);
if (Regs.empty())
return 0;
assert(Regs.size() == 1 &&
"attempt to get single VReg for aggregate or void");
return Regs[0];
}
ValueToVRegInfo::VRegListT &allocateVRegs(const Value &Val);
int getOrCreateFrameIndex(const AllocaInst &AI);
unsigned getMemOpAlignment(const Instruction &I);
MachineBasicBlock &getMBB(const BasicBlock &BB);
void addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred);
SmallVector<MachineBasicBlock *, 1> getMachinePredBBs(CFGEdge Edge) {
auto RemappedEdge = MachinePreds.find(Edge);
if (RemappedEdge != MachinePreds.end())
return RemappedEdge->second;
return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first));
}
public:
IRTranslator();
StringRef getPassName() const override { return "IRTranslator"; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &MF) override;
};
}
#endif