mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
llvm-mc/X86: Implement single instruction encoding interface for MC.
- Note, this is a gigantic hack, with the sole purpose of unblocking further work on the assembler (its also possible to test the mathcer more completely now). - Despite being a hack, its actually good enough to work over all of 403.gcc (although some encodings are probably incorrect). This is a testament to the beauty of X86's MachineInstr, no doubt! ;) llvm-svn: 80234
This commit is contained in:
parent
b11e3eb82f
commit
9a8ec155f7
@ -22,7 +22,9 @@ namespace llvm {
|
||||
class X86TargetMachine;
|
||||
class FunctionPass;
|
||||
class MachineCodeEmitter;
|
||||
class MCCodeEmitter;
|
||||
class JITCodeEmitter;
|
||||
class Target;
|
||||
class formatted_raw_ostream;
|
||||
|
||||
/// createX86ISelDag - This pass converts a legalized DAG into a
|
||||
@ -52,6 +54,8 @@ FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM,
|
||||
FunctionPass *createX86ObjectCodeEmitterPass(X86TargetMachine &TM,
|
||||
ObjectCodeEmitter &OCE);
|
||||
|
||||
MCCodeEmitter *createX86MCCodeEmitter(const Target &, TargetMachine &TM);
|
||||
|
||||
/// createX86EmitCodeToMemory - Returns a pass that converts a register
|
||||
/// allocated function into raw machine code in a dynamically
|
||||
/// allocated chunk of memory.
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -858,3 +860,251 @@ void Emitter<CodeEmitter>::emitInstruction(const MachineInstr &MI,
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 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];
|
||||
|
||||
public:
|
||||
MCSingleInstructionCodeEmitter() { reset(); }
|
||||
|
||||
void reset() {
|
||||
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 emitLabel(uint64_t LabelID) {}
|
||||
virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {}
|
||||
virtual bool earlyResolveAddresses() const { return false; }
|
||||
virtual void addRelocation(const MachineRelocation &MR) { }
|
||||
virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
|
||||
return 0;
|
||||
}
|
||||
virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
|
||||
return 0;
|
||||
}
|
||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
|
||||
return 0;
|
||||
}
|
||||
virtual uintptr_t getLabelAddress(uint64_t LabelID) const {
|
||||
return 0;
|
||||
}
|
||||
virtual void setModuleInfo(MachineModuleInfo* Info) {}
|
||||
};
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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.isMCValue())
|
||||
return false;
|
||||
|
||||
// FIXME: Relocation / fixup.
|
||||
Instr->addOperand(MachineOperand::CreateImm(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) 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;
|
||||
if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1) {
|
||||
Instr->addOperand(MachineOperand::CreateReg(0, false));
|
||||
++CurOp;
|
||||
} 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, 0); CurOp++;
|
||||
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).isMCValue() &&
|
||||
MI.getOperand(0).getMCValue().getSymA() &&
|
||||
!MI.getOperand(0).getMCValue().getSymB())
|
||||
Instr->addOperand(MachineOperand::CreateMBB(DummyMBB));
|
||||
else
|
||||
OK &= AddImmToInstr(MI, Instr, CurOp);
|
||||
}
|
||||
break;
|
||||
|
||||
case X86II::AddRegFrm:
|
||||
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
||||
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, 0); CurOp++;
|
||||
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:
|
||||
OK &= AddRegToInstr(MI, Instr, CurOp++);
|
||||
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) {
|
||||
errs() << "couldn't convert inst '";
|
||||
MI.print(errs());
|
||||
errs() << "' to machine instr:\n";
|
||||
Instr->dump();
|
||||
}
|
||||
|
||||
InstrEmitter->reset();
|
||||
if (OK)
|
||||
Emit->emitInstruction(*Instr, &Desc);
|
||||
OS << InstrEmitter->str();
|
||||
|
||||
Instr->eraseFromParent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Ok, now you can look.
|
||||
MCCodeEmitter *llvm::createX86MCCodeEmitter(const Target &,
|
||||
TargetMachine &TM) {
|
||||
return new X86MCCodeEmitter(static_cast<X86TargetMachine&>(TM));
|
||||
}
|
||||
|
@ -47,6 +47,10 @@ extern "C" void LLVMInitializeX86Target() {
|
||||
// Register the target asm info.
|
||||
RegisterAsmInfoFn A(TheX86_32Target, createMCAsmInfo);
|
||||
RegisterAsmInfoFn B(TheX86_64Target, createMCAsmInfo);
|
||||
|
||||
// Register the code emitter.
|
||||
TargetRegistry::RegisterCodeEmitter(TheX86_32Target, createX86MCCodeEmitter);
|
||||
TargetRegistry::RegisterCodeEmitter(TheX86_64Target, createX86MCCodeEmitter);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user