forked from OSchip/llvm-project
Add support for the -x86-asm-syntax flag, which can be used to choose between
Intel and AT&T style assembly language. The ultimate goal of this is to eliminate the GasBugWorkaroundEmitter class, but for now AT&T style emission is not fully operational. llvm-svn: 16639
This commit is contained in:
parent
4e59a14909
commit
5683260187
|
@ -15,7 +15,8 @@ TARGET = X86
|
|||
# Make sure that tblgen is run, first thing.
|
||||
$(SourceDepend): X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \
|
||||
X86GenRegisterInfo.inc X86GenInstrNames.inc \
|
||||
X86GenInstrInfo.inc X86GenAsmWriter.inc
|
||||
X86GenInstrInfo.inc X86GenATTAsmWriter.inc \
|
||||
X86GenIntelAsmWriter.inc
|
||||
|
||||
TDFILES = $(SourceDir)/$(TARGET).td $(wildcard $(SourceDir)/*.td) \
|
||||
$(SourceDir)/../Target.td
|
||||
|
@ -40,10 +41,14 @@ $(TARGET)GenInstrInfo.inc:: $(TDFILES) $(TBLGEN)
|
|||
@echo "Building $(TARGET).td instruction information with tblgen"
|
||||
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-desc -o $@
|
||||
|
||||
$(TARGET)GenAsmWriter.inc:: $(TDFILES) $(TBLGEN)
|
||||
@echo "Building $(TARGET).td assembly writer with tblgen"
|
||||
$(TARGET)GenATTAsmWriter.inc:: $(TDFILES) $(TBLGEN)
|
||||
@echo "Building $(TARGET).td AT&T assembly writer with tblgen"
|
||||
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-asm-writer -o $@
|
||||
|
||||
$(TARGET)GenIntelAsmWriter.inc:: $(TDFILES) $(TBLGEN)
|
||||
@echo "Building $(TARGET).td Intel assembly writer with tblgen"
|
||||
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-asm-writer -asmwriternum=1 -o $@
|
||||
|
||||
#$(TARGET)GenInstrSelector.inc:: $(TDFILES) $(TBLGEN)
|
||||
# @echo "Building $(TARGET).td instruction selector with tblgen"
|
||||
# $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-selector -o $@
|
||||
|
|
|
@ -47,6 +47,18 @@ def X86InstrInfo : InstrInfo {
|
|||
16];
|
||||
}
|
||||
|
||||
// The X86 target supports two different syntaxes for emitting machine code.
|
||||
// This is controlled by the -x86-asm-syntax={att|intel}
|
||||
def ATTAsmWriter : AsmWriter {
|
||||
string AsmWriterClassName = "ATTAsmPrinter";
|
||||
int Variant = 0;
|
||||
}
|
||||
def IntelAsmWriter : AsmWriter {
|
||||
string AsmWriterClassName = "IntelAsmPrinter";
|
||||
int Variant = 1;
|
||||
}
|
||||
|
||||
|
||||
def X86 : Target {
|
||||
// Specify the callee saved registers.
|
||||
let CalleeSavedRegisters = [ESI, EDI, EBX, EBP];
|
||||
|
@ -56,4 +68,6 @@ def X86 : Target {
|
|||
|
||||
// Information about the instructions...
|
||||
let InstructionSet = X86InstrInfo;
|
||||
|
||||
let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
|
||||
}
|
||||
|
|
|
@ -36,6 +36,16 @@ using namespace llvm;
|
|||
|
||||
namespace {
|
||||
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
|
||||
enum AsmWriterFlavor { att, intel };
|
||||
|
||||
cl::opt<AsmWriterFlavor>
|
||||
AsmWriterFlavor("x86-asm-syntax",
|
||||
cl::desc("Choose style of code to emit from X86 backend:"),
|
||||
cl::values(
|
||||
clEnumVal(att, " Emit AT&T Style"),
|
||||
clEnumVal(intel, " Emit Intel Style"),
|
||||
clEnumValEnd),
|
||||
cl::init(intel));
|
||||
|
||||
struct GasBugWorkaroundEmitter : public MachineCodeEmitter {
|
||||
GasBugWorkaroundEmitter(std::ostream& o)
|
||||
|
@ -67,8 +77,8 @@ namespace {
|
|||
bool firstByte;
|
||||
};
|
||||
|
||||
struct X86AsmPrinter : public AsmPrinter {
|
||||
X86AsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) { }
|
||||
struct X86IntelAsmPrinter : public AsmPrinter {
|
||||
X86IntelAsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) { }
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "X86 Assembly Printer";
|
||||
|
@ -128,12 +138,17 @@ namespace {
|
|||
/// regardless of whether the function is in SSA form.
|
||||
///
|
||||
FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
|
||||
return new X86AsmPrinter(o, tm);
|
||||
if (AsmWriterFlavor != intel) {
|
||||
std::cerr << "AT&T syntax not fully implemented yet!\n";
|
||||
abort();
|
||||
}
|
||||
|
||||
return new X86IntelAsmPrinter(o, tm);
|
||||
}
|
||||
|
||||
|
||||
// Include the auto-generated portion of the assembly writer.
|
||||
#include "X86GenAsmWriter.inc"
|
||||
#include "X86GenIntelAsmWriter.inc"
|
||||
|
||||
|
||||
/// printConstantPool - Print to the current output stream assembly
|
||||
|
@ -141,7 +156,7 @@ FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
|
|||
/// used to print out constants which have been "spilled to memory" by
|
||||
/// the code generator.
|
||||
///
|
||||
void X86AsmPrinter::printConstantPool(MachineConstantPool *MCP) {
|
||||
void X86IntelAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
|
||||
const std::vector<Constant*> &CP = MCP->getConstants();
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
|
@ -159,7 +174,7 @@ void X86AsmPrinter::printConstantPool(MachineConstantPool *MCP) {
|
|||
/// runOnMachineFunction - This uses the printMachineInstruction()
|
||||
/// method to print assembly for each instruction.
|
||||
///
|
||||
bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
setupMachineFunction(MF);
|
||||
O << "\n\n";
|
||||
|
||||
|
@ -207,7 +222,7 @@ static bool isMem(const MachineInstr *MI, unsigned Op) {
|
|||
|
||||
|
||||
|
||||
void X86AsmPrinter::printOp(const MachineOperand &MO,
|
||||
void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
|
||||
bool elideOffsetKeyword /* = false */) {
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
switch (MO.getType()) {
|
||||
|
@ -253,7 +268,7 @@ void X86AsmPrinter::printOp(const MachineOperand &MO,
|
|||
}
|
||||
}
|
||||
|
||||
void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
|
||||
void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
|
||||
assert(isMem(MI, Op) && "Invalid memory reference!");
|
||||
|
||||
if (MI->getOperand(Op).isFrameIndex()) {
|
||||
|
@ -308,7 +323,7 @@ void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
|
|||
/// printMachineInstruction -- Print out a single X86 LLVM instruction
|
||||
/// MI in Intel syntax to the current output stream.
|
||||
///
|
||||
void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
++EmittedInsts;
|
||||
|
||||
// gas bugs:
|
||||
|
@ -349,7 +364,7 @@ void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
|||
}
|
||||
}
|
||||
|
||||
bool X86AsmPrinter::doInitialization(Module &M) {
|
||||
bool X86IntelAsmPrinter::doInitialization(Module &M) {
|
||||
AsmPrinter::doInitialization(M);
|
||||
// Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
|
||||
//
|
||||
|
@ -375,7 +390,7 @@ static void SwitchSection(std::ostream &OS, std::string &CurSection,
|
|||
}
|
||||
}
|
||||
|
||||
bool X86AsmPrinter::doFinalization(Module &M) {
|
||||
bool X86IntelAsmPrinter::doFinalization(Module &M) {
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
std::string CurSection;
|
||||
|
||||
|
|
Loading…
Reference in New Issue