|
|
|
@@ -871,336 +871,3 @@ void Emitter<CodeEmitter>::emitInstruction(const MachineInstr &MI,
|
|
|
|
|
|
|
|
|
|
MCE.processDebugLoc(MI.getDebugLoc(), false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adapt the Emitter / CodeEmitter interfaces to MCCodeEmitter.
|
|
|
|
|
//
|
|
|
|
|
// FIXME: This is a total hack designed to allow work on llvm-mc to proceed
|
|
|
|
|
// without being blocked on various cleanups needed to support a clean interface
|
|
|
|
|
// to instruction encoding.
|
|
|
|
|
//
|
|
|
|
|
// Look away!
|
|
|
|
|
|
|
|
|
|
#include "llvm/DerivedTypes.h"
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
class MCSingleInstructionCodeEmitter : public MachineCodeEmitter {
|
|
|
|
|
uint8_t Data[256];
|
|
|
|
|
const MCInst *CurrentInst;
|
|
|
|
|
SmallVectorImpl<MCFixup> *FixupList;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MCSingleInstructionCodeEmitter() { reset(0, 0); }
|
|
|
|
|
|
|
|
|
|
void reset(const MCInst *Inst, SmallVectorImpl<MCFixup> *Fixups) {
|
|
|
|
|
CurrentInst = Inst;
|
|
|
|
|
FixupList = Fixups;
|
|
|
|
|
BufferBegin = Data;
|
|
|
|
|
BufferEnd = array_endof(Data);
|
|
|
|
|
CurBufferPtr = Data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StringRef str() {
|
|
|
|
|
return StringRef(reinterpret_cast<char*>(BufferBegin),
|
|
|
|
|
CurBufferPtr - BufferBegin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void startFunction(MachineFunction &F) {}
|
|
|
|
|
virtual bool finishFunction(MachineFunction &F) { return false; }
|
|
|
|
|
virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {}
|
|
|
|
|
virtual bool earlyResolveAddresses() const { return false; }
|
|
|
|
|
virtual void addRelocation(const MachineRelocation &MR) {
|
|
|
|
|
unsigned Offset = 0, OpIndex = 0, Kind = MR.getRelocationType();
|
|
|
|
|
|
|
|
|
|
// This form is only used in one case, for branches.
|
|
|
|
|
if (MR.isBasicBlock()) {
|
|
|
|
|
Offset = unsigned(MR.getMachineCodeOffset());
|
|
|
|
|
OpIndex = 0;
|
|
|
|
|
} else {
|
|
|
|
|
assert(MR.isJumpTableIndex() && "Unexpected relocation!");
|
|
|
|
|
|
|
|
|
|
Offset = unsigned(MR.getMachineCodeOffset());
|
|
|
|
|
|
|
|
|
|
// The operand index is encoded as the first byte of the fake operand.
|
|
|
|
|
OpIndex = MR.getJumpTableIndex();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MCOperand Op = CurrentInst->getOperand(OpIndex);
|
|
|
|
|
assert(Op.isExpr() && "FIXME: Not yet implemented!");
|
|
|
|
|
FixupList->push_back(MCFixup::Create(Offset, Op.getExpr(),
|
|
|
|
|
MCFixupKind(FirstTargetFixupKind + Kind)));
|
|
|
|
|
}
|
|
|
|
|
virtual void setModuleInfo(MachineModuleInfo* Info) {}
|
|
|
|
|
|
|
|
|
|
// Interface functions which should never get called in our usage.
|
|
|
|
|
|
|
|
|
|
virtual void emitLabel(uint64_t LabelID) {
|
|
|
|
|
assert(0 && "Unexpected code emitter call!");
|
|
|
|
|
}
|
|
|
|
|
virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
|
|
|
|
|
assert(0 && "Unexpected code emitter call!");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
|
|
|
|
|
assert(0 && "Unexpected code emitter call!");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
|
|
|
|
|
assert(0 && "Unexpected code emitter call!");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
virtual uintptr_t getLabelAddress(uint64_t LabelID) const {
|
|
|
|
|
assert(0 && "Unexpected code emitter call!");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class X86MCCodeEmitter : public MCCodeEmitter {
|
|
|
|
|
X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
|
|
|
|
|
void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
X86TargetMachine &TM;
|
|
|
|
|
llvm::Function *DummyF;
|
|
|
|
|
TargetData *DummyTD;
|
|
|
|
|
mutable llvm::MachineFunction *DummyMF;
|
|
|
|
|
llvm::MachineBasicBlock *DummyMBB;
|
|
|
|
|
|
|
|
|
|
MCSingleInstructionCodeEmitter *InstrEmitter;
|
|
|
|
|
Emitter<MachineCodeEmitter> *Emit;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
X86MCCodeEmitter(X86TargetMachine &_TM) : TM(_TM) {
|
|
|
|
|
// Verily, thou shouldst avert thine eyes.
|
|
|
|
|
const llvm::FunctionType *FTy =
|
|
|
|
|
FunctionType::get(llvm::Type::getVoidTy(getGlobalContext()), false);
|
|
|
|
|
DummyF = Function::Create(FTy, GlobalValue::InternalLinkage);
|
|
|
|
|
DummyTD = new TargetData("");
|
|
|
|
|
DummyMF = new MachineFunction(DummyF, TM, 0);
|
|
|
|
|
DummyMBB = DummyMF->CreateMachineBasicBlock();
|
|
|
|
|
|
|
|
|
|
InstrEmitter = new MCSingleInstructionCodeEmitter();
|
|
|
|
|
Emit = new Emitter<MachineCodeEmitter>(TM, *InstrEmitter,
|
|
|
|
|
*TM.getInstrInfo(),
|
|
|
|
|
*DummyTD, false);
|
|
|
|
|
}
|
|
|
|
|
~X86MCCodeEmitter() {
|
|
|
|
|
delete Emit;
|
|
|
|
|
delete InstrEmitter;
|
|
|
|
|
delete DummyMF;
|
|
|
|
|
delete DummyF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned getNumFixupKinds() const {
|
|
|
|
|
return 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
|
|
|
|
|
static MCFixupKindInfo Infos[] = {
|
|
|
|
|
{ "reloc_pcrel_word", 0, 4 * 8 },
|
|
|
|
|
{ "reloc_picrel_word", 0, 4 * 8 },
|
|
|
|
|
{ "reloc_absolute_word", 0, 4 * 8 },
|
|
|
|
|
{ "reloc_absolute_word_sext", 0, 4 * 8 },
|
|
|
|
|
{ "reloc_absolute_dword", 0, 8 * 8 }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
assert(Kind >= FirstTargetFixupKind && Kind < MaxTargetFixupKind &&
|
|
|
|
|
"Invalid kind!");
|
|
|
|
|
return Infos[Kind - FirstTargetFixupKind];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AddRegToInstr(const MCInst &MI, MachineInstr *Instr,
|
|
|
|
|
unsigned Start) const {
|
|
|
|
|
if (Start + 1 > MI.getNumOperands())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const MCOperand &Op = MI.getOperand(Start);
|
|
|
|
|
if (!Op.isReg()) return false;
|
|
|
|
|
|
|
|
|
|
Instr->addOperand(MachineOperand::CreateReg(Op.getReg(), false));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AddImmToInstr(const MCInst &MI, MachineInstr *Instr,
|
|
|
|
|
unsigned Start) const {
|
|
|
|
|
if (Start + 1 > MI.getNumOperands())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const MCOperand &Op = MI.getOperand(Start);
|
|
|
|
|
if (Op.isImm()) {
|
|
|
|
|
Instr->addOperand(MachineOperand::CreateImm(Op.getImm()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (!Op.isExpr())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const MCExpr *Expr = Op.getExpr();
|
|
|
|
|
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) {
|
|
|
|
|
Instr->addOperand(MachineOperand::CreateImm(CE->getValue()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fake this as an external symbol to the code emitter to add a relcoation
|
|
|
|
|
// entry we will recognize.
|
|
|
|
|
Instr->addOperand(MachineOperand::CreateJTI(Start, 0));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AddLMemToInstr(const MCInst &MI, MachineInstr *Instr,
|
|
|
|
|
unsigned Start) const {
|
|
|
|
|
return (AddRegToInstr(MI, Instr, Start + 0) &&
|
|
|
|
|
AddImmToInstr(MI, Instr, Start + 1) &&
|
|
|
|
|
AddRegToInstr(MI, Instr, Start + 2) &&
|
|
|
|
|
AddImmToInstr(MI, Instr, Start + 3));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AddMemToInstr(const MCInst &MI, MachineInstr *Instr,
|
|
|
|
|
unsigned Start) const {
|
|
|
|
|
return (AddRegToInstr(MI, Instr, Start + 0) &&
|
|
|
|
|
AddImmToInstr(MI, Instr, Start + 1) &&
|
|
|
|
|
AddRegToInstr(MI, Instr, Start + 2) &&
|
|
|
|
|
AddImmToInstr(MI, Instr, Start + 3) &&
|
|
|
|
|
AddRegToInstr(MI, Instr, Start + 4));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|
|
|
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
|
|
|
|
// Don't look yet!
|
|
|
|
|
|
|
|
|
|
// Convert the MCInst to a MachineInstr so we can (ab)use the regular
|
|
|
|
|
// emitter.
|
|
|
|
|
const X86InstrInfo &II = *TM.getInstrInfo();
|
|
|
|
|
const TargetInstrDesc &Desc = II.get(MI.getOpcode());
|
|
|
|
|
MachineInstr *Instr = DummyMF->CreateMachineInstr(Desc, DebugLoc());
|
|
|
|
|
DummyMBB->push_back(Instr);
|
|
|
|
|
|
|
|
|
|
unsigned Opcode = MI.getOpcode();
|
|
|
|
|
unsigned NumOps = MI.getNumOperands();
|
|
|
|
|
unsigned CurOp = 0;
|
|
|
|
|
bool AddTied = false;
|
|
|
|
|
if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1)
|
|
|
|
|
AddTied = true;
|
|
|
|
|
else if (NumOps > 2 &&
|
|
|
|
|
Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0)
|
|
|
|
|
// Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
|
|
|
|
|
--NumOps;
|
|
|
|
|
|
|
|
|
|
bool OK = true;
|
|
|
|
|
switch (Desc.TSFlags & X86II::FormMask) {
|
|
|
|
|
case X86II::MRMDestReg:
|
|
|
|
|
case X86II::MRMSrcReg:
|
|
|
|
|
// Matching doesn't fill this in completely, we have to choose operand 0
|
|
|
|
|
// for a tied register.
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
|
|
|
|
if (AddTied)
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++ - 1);
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
|
|
|
|
if (CurOp < NumOps)
|
|
|
|
|
OK &= AddImmToInstr(MI, Instr, CurOp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case X86II::RawFrm:
|
|
|
|
|
if (CurOp < NumOps) {
|
|
|
|
|
// Hack to make branches work.
|
|
|
|
|
if (!(Desc.TSFlags & X86II::ImmMask) &&
|
|
|
|
|
MI.getOperand(0).isExpr() &&
|
|
|
|
|
isa<MCSymbolRefExpr>(MI.getOperand(0).getExpr()))
|
|
|
|
|
Instr->addOperand(MachineOperand::CreateMBB(DummyMBB));
|
|
|
|
|
else
|
|
|
|
|
OK &= AddImmToInstr(MI, Instr, CurOp);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case X86II::AddRegFrm:
|
|
|
|
|
// Matching doesn't fill this in completely, we have to choose operand 0
|
|
|
|
|
// for a tied register.
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
|
|
|
|
if (AddTied)
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++ - 1);
|
|
|
|
|
if (CurOp < NumOps)
|
|
|
|
|
OK &= AddImmToInstr(MI, Instr, CurOp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case X86II::MRM0r: case X86II::MRM1r:
|
|
|
|
|
case X86II::MRM2r: case X86II::MRM3r:
|
|
|
|
|
case X86II::MRM4r: case X86II::MRM5r:
|
|
|
|
|
case X86II::MRM6r: case X86II::MRM7r:
|
|
|
|
|
// Matching doesn't fill this in completely, we have to choose operand 0
|
|
|
|
|
// for a tied register.
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
|
|
|
|
if (AddTied)
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++ - 1);
|
|
|
|
|
if (CurOp < NumOps)
|
|
|
|
|
OK &= AddImmToInstr(MI, Instr, CurOp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case X86II::MRM0m: case X86II::MRM1m:
|
|
|
|
|
case X86II::MRM2m: case X86II::MRM3m:
|
|
|
|
|
case X86II::MRM4m: case X86II::MRM5m:
|
|
|
|
|
case X86II::MRM6m: case X86II::MRM7m:
|
|
|
|
|
OK &= AddMemToInstr(MI, Instr, CurOp); CurOp += 5;
|
|
|
|
|
if (CurOp < NumOps)
|
|
|
|
|
OK &= AddImmToInstr(MI, Instr, CurOp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case X86II::MRMSrcMem:
|
|
|
|
|
// Matching doesn't fill this in completely, we have to choose operand 0
|
|
|
|
|
// for a tied register.
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
|
|
|
|
if (AddTied)
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp++ - 1);
|
|
|
|
|
if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r ||
|
|
|
|
|
Opcode == X86::LEA16r || Opcode == X86::LEA32r)
|
|
|
|
|
OK &= AddLMemToInstr(MI, Instr, CurOp);
|
|
|
|
|
else
|
|
|
|
|
OK &= AddMemToInstr(MI, Instr, CurOp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case X86II::MRMDestMem:
|
|
|
|
|
OK &= AddMemToInstr(MI, Instr, CurOp); CurOp += 5;
|
|
|
|
|
OK &= AddRegToInstr(MI, Instr, CurOp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
case X86II::MRMInitReg:
|
|
|
|
|
case X86II::Pseudo:
|
|
|
|
|
OK = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!OK) {
|
|
|
|
|
dbgs() << "couldn't convert inst '";
|
|
|
|
|
MI.dump();
|
|
|
|
|
dbgs() << "' to machine instr:\n";
|
|
|
|
|
Instr->dump();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InstrEmitter->reset(&MI, &Fixups);
|
|
|
|
|
if (OK)
|
|
|
|
|
Emit->emitInstruction(*Instr, &Desc);
|
|
|
|
|
OS << InstrEmitter->str();
|
|
|
|
|
|
|
|
|
|
Instr->eraseFromParent();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
|
|
|
|
|
|
static cl::opt<bool> EnableNewEncoder("enable-new-x86-encoder",
|
|
|
|
|
cl::ReallyHidden);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ok, now you can look.
|
|
|
|
|
MCCodeEmitter *llvm::createHeinousX86MCCodeEmitter(const Target &T,
|
|
|
|
|
TargetMachine &TM,
|
|
|
|
|
MCContext &Ctx) {
|
|
|
|
|
|
|
|
|
|
// FIXME: Remove the heinous one when the new one works.
|
|
|
|
|
if (EnableNewEncoder) {
|
|
|
|
|
if (TM.getTargetData()->getPointerSize() == 4)
|
|
|
|
|
return createX86_32MCCodeEmitter(T, TM, Ctx);
|
|
|
|
|
return createX86_64MCCodeEmitter(T, TM, Ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new X86MCCodeEmitter(static_cast<X86TargetMachine&>(TM));
|
|
|
|
|
}
|
|
|
|
|