//===-- X86/Printer.cpp - Convert X86 LLVM code to Intel assembly ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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 -print-machineinstrs' on X86.
//
//===----------------------------------------------------------------------===//
#include "X86.h"
#include "X86InstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"
#include "Support/CommandLine.h"
namespace {
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
// 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.
///
std::ostream &O;
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
TargetMachine &TM;
/// Name-mangler for global names.
///
Mangler *Mang;
Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { }
/// We name each basic block in a Function with a unique number, so
/// that we can consistently refer to them later. This is cleared
/// at the beginning of each call to runOnMachineFunction().
///
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
/// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to
/// runOnMachineFunction().
///
std::string CurrentFnName;
virtual const char *getPassName() const {
return "X86 Assembly Printer";
}
void checkImplUses (const TargetInstrDescriptor &Desc);
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO,
bool elideOffsetKeyword = false);
void printMemReference(const MachineInstr *MI, unsigned Op);
void printConstantPool(MachineConstantPool *MCP);
bool runOnMachineFunction(MachineFunction &F);
std::string ConstantExprToString(const ConstantExpr* CE);
std::string valToExprString(const Value* V);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
void printConstantValueOnly(const Constant* CV);
void printSingleConstantValue(const Constant* CV);
};
} // end of anonymous namespace
/// createX86CodePrinterPass - Returns a pass that prints the X86
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
return new Printer(o, tm);
}
/// valToExprString - Helper function for ConstantExprToString().
/// Appends result to argument string S.
///
std::string Printer::valToExprString(const Value* V) {
std::string S;
bool failed = false;
if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
S += std::string(CB == ConstantBool::True ? "1" : "0");
else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
S += itostr(CI->getValue());
else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
S += utostr(CI->getValue());
else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
S += ftostr(CFP->getValue());
else if (isa<ConstantPointerNull>(CV))
S += "0";
else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
S += valToExprString(CPR->getValue());
else if (const ConstantExpr *CE =