// This file contains a printer that converts from our internal
// representation of machine-dependent LLVM code to Intel-format
// assembly language. This printer is the output mechanism used
-// by `llc' and `lli -printmachineinstrs' on X86.
+// by `llc' and `lli -print-machineinstrs' on X86.
//
//===----------------------------------------------------------------------===//
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/Mangler.h"
#include "Support/StringExtras.h"
+#include "Support/CommandLine.h"
namespace {
+ // FIXME: This should be automatically picked up by autoconf from the C
+ // frontend
+ cl::opt<bool> EmitCygwin("enable-cygwin-compatible-output", cl::Hidden,
+ cl::desc("Emit X86 assembly code suitable for consumption by cygwin"));
+
struct Printer : public MachineFunctionPass {
/// Output stream on which we're printing assembly code.
///
return "X86 Assembly Printer";
}
+ void checkImplUses (const TargetInstrDescriptor &Desc);
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO,
bool elideOffsetKeyword = false);
/// and return this as a string.
///
std::string Printer::ConstantExprToString(const ConstantExpr* CE) {
- std::string S;
const TargetData &TD = TM.getTargetData();
switch(CE->getOpcode()) {
case Instruction::GetElementPtr:
{ // generate a symbolic expression for the byte address
const Value* ptrVal = CE->getOperand(0);
std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
- S += "(" + valToExprString(ptrVal) + ") + ("
- + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
- break;
+ if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec))
+ return "(" + valToExprString(ptrVal) + ") + " + utostr(Offset);
+ else
+ return valToExprString(ptrVal);
}
case Instruction::Cast:
|| (isa<PointerType>(Ty)
&& (OpTy == Type::LongTy || OpTy == Type::ULongTy)))
|| (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
- && (OpTy-> isLosslesslyConvertibleTo(Ty))))
+ && (OpTy->isLosslesslyConvertibleTo(Ty))))
&& "FIXME: Don't yet support this kind of constant cast expr");
- S += "(" + valToExprString(Op) + ")";
+ return "(" + valToExprString(Op) + ")";
}
- break;
case Instruction::Add:
- S += "(" + valToExprString(CE->getOperand(0)) + ") + ("
- + valToExprString(CE->getOperand(1)) + ")";
- break;
+ return "(" + valToExprString(CE->getOperand(0)) + ") + ("
+ + valToExprString(CE->getOperand(1)) + ")";
default:
assert(0 && "Unsupported operator in ConstantExprToString()");
- break;
+ return "";
}
-
- return S;
}
/// printSingleConstantValue - Print a single constant value.
O << "\t.text\n";
O << "\t.align 16\n";
O << "\t.globl\t" << CurrentFnName << "\n";
- O << "\t.type\t" << CurrentFnName << ", @function\n";
+ if (!EmitCygwin)
+ O << "\t.type\t" << CurrentFnName << ", @function\n";
O << CurrentFnName << ":\n";
// Number each basic block so that we can consistently refer to them
MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate();
}
+
+
void Printer::printOp(const MachineOperand &MO,
bool elideOffsetKeyword /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
}
// FALLTHROUGH
case MachineOperand::MO_MachineRegister:
- if (MO.getReg() < MRegisterInfo::FirstVirtualRegister)
+ if (MO.getReg() < MRegisterInfo::FirstVirtualRegister) {
+ // Bug Workaround: See note in Printer::doInitialization about %.
O << RI.get(MO.getReg()).Name;
- else
+ } else
O << "%reg" << MO.getReg();
return;
}
void Printer::printMemReference(const MachineInstr *MI, unsigned Op) {
- const MRegisterInfo &RI = *TM.getRegisterInfo();
assert(isMem(MI, Op) && "Invalid memory reference!");
if (MI->getOperand(Op).isFrameIndex()) {
O << "]";
}
+/// checkImplUses - Emit the implicit-use registers for the
+/// instruction described by DESC, if its PrintImplUses flag is set.
+///
+void Printer::checkImplUses (const TargetInstrDescriptor &Desc) {
+ const MRegisterInfo &RI = *TM.getRegisterInfo();
+ if (Desc.TSFlags & X86II::PrintImplUses) {
+ for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
+ // Bug Workaround: See note in Printer::doInitialization about %.
+ O << ", %" << RI.get(*p).Name;
+ }
+ }
+}
+
/// printMachineInstruction -- Print out a single X86 LLVM instruction
/// MI in Intel syntax to the current output stream.
///
unsigned Opcode = MI->getOpcode();
const TargetInstrInfo &TII = TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode);
- const MRegisterInfo &RI = *TM.getRegisterInfo();
switch (Desc.TSFlags & X86II::FormMask) {
case X86II::Pseudo:
O << ", ";
printOp(MI->getOperand(1));
}
- if (Desc.TSFlags & X86II::PrintImplUses) {
- for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
- O << ", " << RI.get(*p).Name;
- }
- }
+ checkImplUses(Desc);
O << "\n";
return;
}
O << ", ";
printOp(MI->getOperand(MI->getNumOperands()-1));
}
- if (Desc.TSFlags & X86II::PrintImplUses) {
- for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
- O << ", " << RI.get(*p).Name;
- }
- }
+ checkImplUses(Desc);
O << "\n";
return;
}
}
-bool Printer::doInitialization(Module &M)
-{
- // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly,
- // with no % decorations on register names.
- O << "\t.intel_syntax noprefix\n";
- Mang = new Mangler(M);
+bool Printer::doInitialization(Module &M) {
+ // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
+ //
+ // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
+ // instruction as a reference to the register named sp, and if you try to
+ // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
+ // before being looked up in the symbol table. This creates spurious
+ // `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
+ // mode, and decorate all register names with percent signs.
+ //
+ // Cygwin presumably doesn't have this problem, so drop the %'s.
+ //
+ O << "\t.intel_syntax\n";
+ Mang = new Mangler(M, EmitCygwin);
return false; // success
}