"llvm/test/git@repo.hca.bsc.es:lalbano/llvm-bpevl.git" did not exist on "7fa503ef4aaddc1c31dd36d970aa6609383e1718"
Newer
Older
//===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly -----===//
//
// The LLVM Compiler Infrastructure
//
// This file 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 AT&T format assembly
// language. This printer is the output mechanism used by `llc'.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "X86ATTAsmPrinter.h"
#include "X86.h"
#include "X86COFF.h"
#include "X86MachineFunctionInfo.h"
#include "X86TargetMachine.h"
#include "X86MCAsmInfo.h"
#include "llvm/CallingConv.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
Bill Wendling
committed
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
static cl::opt<bool> NewAsmPrinter("experimental-asm-printer",
cl::Hidden);
//===----------------------------------------------------------------------===//
// Primitive Helper Functions.
//===----------------------------------------------------------------------===//
Chris Lattner
committed
void X86ATTAsmPrinter::PrintPICBaseSymbol() const {
// FIXME: the actual label generated doesn't matter here! Just mangle in
// something unique (the function number) with Private prefix.
Chris Lattner
committed
O << "\"L" << getFunctionNumber() << "$pb\"";
else {
assert(Subtarget->isTargetELF() && "Don't know how to print PIC label!");
O << ".Lllvm$" << getFunctionNumber() << ".$piclabel";
}
}
MCSymbol *X86ATTAsmPrinter::GetPICBaseSymbol() {
// FIXME: the actual label generated doesn't matter here! Just mangle in
// something unique (the function number) with Private prefix.
std::string Name;
if (Subtarget->isTargetDarwin()) {
Name = "L" + utostr(getFunctionNumber())+"$pb";
} else {
assert(Subtarget->isTargetELF() && "Don't know how to print PIC label!");
Name = ".Lllvm$" + utostr(getFunctionNumber())+".$piclabel";
return OutContext.GetOrCreateSymbol(Name);
static X86MachineFunctionInfo calculateFunctionInfo(const Function *F,
const TargetData *TD) {
X86MachineFunctionInfo Info;
uint64_t Size = 0;
switch (F->getCallingConv()) {
case CallingConv::X86_StdCall:
Info.setDecorationStyle(StdCall);
break;
case CallingConv::X86_FastCall:
Info.setDecorationStyle(FastCall);
break;
default:
return Info;
}
unsigned argNum = 1;
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI, ++argNum) {
const Type* Ty = AI->getType();
// 'Dereference' type in case of byval parameter attribute
Ty = cast<PointerType>(Ty)->getElementType();
// Size should be aligned to DWORD boundary
Size += ((TD->getTypeAllocSize(Ty) + 3)/4)*4;
}
// We're not supporting tooooo huge arguments :)
Info.setBytesToPopOnReturn((unsigned int)Size);
return Info;
}
/// DecorateCygMingName - Query FunctionInfoMap and use this information for
/// various name decorations for Cygwin and MingW.
void X86ATTAsmPrinter::DecorateCygMingName(std::string &Name,
const GlobalValue *GV) {
assert(Subtarget->isTargetCygMing() && "This is only for cygwin and mingw");
const Function *F = dyn_cast<Function>(GV);
if (!F) return;
// Save function name for later type emission.
if (F->isDeclaration())
CygMingStubs.insert(Name);
// We don't want to decorate non-stdcall or non-fastcall functions right now
unsigned CC = F->getCallingConv();
if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall)
return;
const X86MachineFunctionInfo *Info;
FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F);
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
if (info_item == FunctionInfoMap.end()) {
// Calculate apropriate function info and populate map
FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData());
Info = &FunctionInfoMap[F];
} else {
Info = &info_item->second;
}
const FunctionType *FT = F->getFunctionType();
switch (Info->getDecorationStyle()) {
case None:
break;
case StdCall:
// "Pure" variadic functions do not receive @0 suffix.
if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
(FT->getNumParams() == 1 && F->hasStructRetAttr()))
Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
break;
case FastCall:
// "Pure" variadic functions do not receive @0 suffix.
if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
(FT->getNumParams() == 1 && F->hasStructRetAttr()))
Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
if (Name[0] == '_') {
Name[0] = '@';
} else {
Name = '@' + Name;
}
break;
default:
llvm_unreachable("Unsupported DecorationStyle");
void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
Bill Wendling
committed
unsigned FnAlign = MF.getAlignment();
const Function *F = MF.getFunction();
if (Subtarget->isTargetCygMing())
DecorateCygMingName(CurrentFnName, F);
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
switch (F->getLinkage()) {
default: llvm_unreachable("Unknown linkage type!");
case Function::InternalLinkage: // Symbols default to internal.
break;
case Function::DLLExportLinkage:
case Function::ExternalLinkage:
O << "\t.globl\t" << CurrentFnName << '\n';
break;
case Function::LinkerPrivateLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
O << "\t.globl\t" << CurrentFnName << '\n';
O << MAI->getWeakDefDirective() << CurrentFnName << '\n';
O << "\t.globl\t" << CurrentFnName << "\n"
"\t.linkonce discard\n";
} else {
O << "\t.weak\t" << CurrentFnName << '\n';
}
break;
}
Anton Korobeynikov
committed
printVisibility(CurrentFnName, F->getVisibility());
if (Subtarget->isTargetELF())
O << "\t.type\t" << CurrentFnName << ",@function\n";
else if (Subtarget->isTargetCygMing()) {
O << "\t.def\t " << CurrentFnName
<< ";\t.scl\t" <<
(F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT)
<< ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
<< ";\t.endef\n";
}
O << CurrentFnName << ':';
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << ' ';
WriteAsOperand(O, F, /*PrintType=*/false, F->getParent());
}
O << '\n';
// Add some workaround for linkonce linkage on Cygwin\MinGW
(F->hasLinkOnceLinkage() || F->hasWeakLinkage()))
O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n";
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
const Function *F = MF.getFunction();
unsigned CC = F->getCallingConv();
SetupMachineFunction(MF);
O << "\n\n";
// Populate function information map. Actually, We don't want to populate
// non-stdcall or non-fastcall functions' information right now.
if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall)
FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>();
// Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool());
if (F->hasDLLExportLinkage())
DLLExportedFns.insert(Mang->getMangledName(F));
// Print the 'header' of function
emitFunctionHeader(MF);
// Emit pre-function debug and/or EH information.
if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling())
// Print out code for the function.
bool hasAnyRealCode = false;
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
// This is an entry block or a block that's only reachable via a
// fallthrough edge. In non-VerboseAsm mode, don't print the label.
} else {
printBasicBlockLabel(I, true, true, VerboseAsm);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
// Print the assembly for the instruction.
if (!II->isLabel())
hasAnyRealCode = true;
printMachineInstruction(II);
}
}
Evan Cheng
committed
if (Subtarget->isTargetDarwin() && !hasAnyRealCode) {
// If the function is empty, then we need to emit *something*. Otherwise,
// the function's label might be associated with something that it wasn't
// meant to be associated with. We emit a noop in this situation.
// We are assuming inline asms are code.
O << "\tnop\n";
}
if (MAI->hasDotTypeDotSizeDirective())
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
// Emit post-function debug information.
if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling())
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
// We didn't modify anything.
return false;
}
/// printSymbolOperand - Print a raw symbol reference operand. This handles
/// jump tables, constant pools, global address and external symbols, all of
/// which print to a label with various suffixes for relocation types etc.
Chris Lattner
committed
void X86ATTAsmPrinter::printSymbolOperand(const MachineOperand &MO) {
switch (MO.getType()) {
default: llvm_unreachable("unknown symbol type!");
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
<< MO.getIndex();
break;
O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
<< MO.getIndex();
break;
case MachineOperand::MO_GlobalAddress: {
Anton Korobeynikov
committed
const GlobalValue *GV = MO.getGlobal();
Chris Lattner
committed
const char *Suffix = "";
if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
Suffix = "$stub";
else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
Suffix = "$non_lazy_ptr";
std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0');
if (Subtarget->isTargetCygMing())
DecorateCygMingName(Name, GV);
Chris Lattner
committed
// Handle dllimport linkage.
if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
Name = "__imp_" + Name;
if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE)
GVStubs[Name] = Mang->getMangledName(GV);
else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
HiddenGVStubs[Name] = Mang->getMangledName(GV);
else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
FnStubs[Name] = Mang->getMangledName(GV);
// If the name begins with a dollar-sign, enclose it in parens. We do this
// to avoid having it look like an integer immediate to the assembler.
if (Name[0] == '$')
O << '(' << Name << ')';
else
O << Name;
printOffset(MO.getOffset());
break;
std::string Name = Mang->makeNameProper(MO.getSymbolName());
if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
FnStubs[Name+"$stub"] = Name;
Name += "$stub";
}
// If the name begins with a dollar-sign, enclose it in parens. We do this
// to avoid having it look like an integer immediate to the assembler.
if (Name[0] == '$')
O << '(' << Name << ')';
else
O << Name;
break;
switch (MO.getTargetFlags()) {
default:
llvm_unreachable("Unknown target flag on GV operand");
case X86II::MO_NO_FLAG: // No flag.
break;
case X86II::MO_DARWIN_NONLAZY:
case X86II::MO_DARWIN_HIDDEN_NONLAZY:
case X86II::MO_DLLIMPORT:
case X86II::MO_DARWIN_STUB:
// These affect the name of the symbol, not any suffix.
break;
case X86II::MO_GOT_ABSOLUTE_ADDRESS:
O << " + [.-";
PrintPICBaseSymbol();
O << ']';
break;
case X86II::MO_PIC_BASE_OFFSET:
case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
O << '-';
PrintPICBaseSymbol();
break;
case X86II::MO_TLSGD: O << "@TLSGD"; break;
case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break;
case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
case X86II::MO_TPOFF: O << "@TPOFF"; break;
case X86II::MO_NTPOFF: O << "@NTPOFF"; break;
case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break;
case X86II::MO_GOT: O << "@GOT"; break;
case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
case X86II::MO_PLT: O << "@PLT"; break;
}
}
/// print_pcrel_imm - This is used to print an immediate value that ends up
/// being encoded as a pc-relative value. These print slightly differently, for
/// example, a $ is not emitted.
void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: llvm_unreachable("Unknown pcrel immediate operand");
case MachineOperand::MO_Immediate:
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB(), false, false, false);
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
printSymbolOperand(MO);
return;
}
}
Chris Lattner
committed
void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: llvm_unreachable("unknown operand type!");
Chris Lattner
committed
case MachineOperand::MO_Register: {
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
"Virtual registers should not make it this far!");
O << '%';
unsigned Reg = MO.getReg();
if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
Owen Anderson
committed
EVT VT = (strcmp(Modifier+6,"64") == 0) ?
Owen Anderson
committed
MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
Chris Lattner
committed
Reg = getX86SubSuperRegister(Reg, VT);
}
O << TRI->getAsmName(Reg);
return;
}
case MachineOperand::MO_Immediate:
O << '$' << MO.getImm();
return;
case MachineOperand::MO_JumpTableIndex:
case MachineOperand::MO_ConstantPoolIndex:
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol: {
Chris Lattner
committed
O << '$';
Chris Lattner
committed
printSymbolOperand(MO);
break;
}
}
}
void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
Chris Lattner
committed
unsigned char value = MI->getOperand(Op).getImm();
assert(value <= 7 && "Invalid ssecc argument!");
switch (value) {
case 0: O << "eq"; break;
case 1: O << "lt"; break;
case 2: O << "le"; break;
case 3: O << "unord"; break;
case 4: O << "neq"; break;
case 5: O << "nlt"; break;
case 6: O << "nle"; break;
case 7: O << "ord"; break;
}
}
void X86ATTAsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier) {
const MachineOperand &BaseReg = MI->getOperand(Op);
const MachineOperand &IndexReg = MI->getOperand(Op+2);
const MachineOperand &DispSpec = MI->getOperand(Op+3);
// If we really don't want to print out (rip), don't.
bool HasBaseReg = BaseReg.getReg() != 0;
if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") &&
BaseReg.getReg() == X86::RIP)
HasBaseReg = false;
// HasParenPart - True if we will print out the () part of the mem ref.
bool HasParenPart = IndexReg.getReg() || HasBaseReg;
if (DispSpec.isImm()) {
int DispVal = DispSpec.getImm();
if (DispVal || !HasParenPart)
O << DispVal;
} else {
assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
DispSpec.isJTI() || DispSpec.isSymbol());
Chris Lattner
committed
printSymbolOperand(MI->getOperand(Op+3));
assert(IndexReg.getReg() != X86::ESP &&
"X86 doesn't allow scaling by ESP");
O << '(';
if (HasBaseReg)
printOperand(MI, Op, Modifier);
if (IndexReg.getReg()) {
O << ',';
printOperand(MI, Op+2, Modifier);
unsigned ScaleVal = MI->getOperand(Op+1).getImm();
if (ScaleVal != 1)
O << ',' << ScaleVal;
O << ')';
}
}
void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier) {
assert(isMem(MI, Op) && "Invalid memory reference!");
const MachineOperand &Segment = MI->getOperand(Op+4);
printOperand(MI, Op+4, Modifier);
O << ':';
}
printLeaMemReference(MI, Op, Modifier);
void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
if (!MAI->getSetDirective())
Anton Korobeynikov
committed
// We don't need .set machinery if we have GOT-style relocations
if (Subtarget->isPICStyleGOT())
return;
O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
Evan Cheng
committed
printBasicBlockLabel(MBB, false, false, false);
O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
Chris Lattner
committed
else {
O << '-';
PrintPICBaseSymbol();
O << '\n';
}
Chris Lattner
committed
void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
Chris Lattner
committed
PrintPICBaseSymbol();
O << '\n';
PrintPICBaseSymbol();
O << ':';
Anton Korobeynikov
committed
void X86ATTAsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
const MachineBasicBlock *MBB,
unsigned uid) const {
Anton Korobeynikov
committed
const char *JTEntryDirective = MJTI->getEntrySize() == 4 ?
MAI->getData32bitsDirective() : MAI->getData64bitsDirective();
Anton Korobeynikov
committed
O << JTEntryDirective << ' ';
if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStubPIC()) {
O << MAI->getPrivateGlobalPrefix() << getFunctionNumber()
Chris Lattner
committed
<< '_' << uid << "_set_" << MBB->getNumber();
} else if (Subtarget->isPICStyleGOT()) {
printBasicBlockLabel(MBB, false, false, false);
O << "@GOTOFF";
Anton Korobeynikov
committed
} else
Evan Cheng
committed
printBasicBlockLabel(MBB, false, false, false);
Anton Korobeynikov
committed
}
bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) {
unsigned Reg = MO.getReg();
switch (Mode) {
default: return true; // Unknown mode.
case 'b': // Print QImode register
Owen Anderson
committed
Reg = getX86SubSuperRegister(Reg, MVT::i8);
break;
case 'h': // Print QImode high register
Owen Anderson
committed
Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
break;
case 'w': // Print HImode register
Owen Anderson
committed
Reg = getX86SubSuperRegister(Reg, MVT::i16);
break;
case 'k': // Print SImode register
Owen Anderson
committed
Reg = getX86SubSuperRegister(Reg, MVT::i32);
case 'q': // Print DImode register
Owen Anderson
committed
Reg = getX86SubSuperRegister(Reg, MVT::i64);
break;
O << '%'<< TRI->getAsmName(Reg);
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode) {
// Does this asm operand have a single letter operand modifier?
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
Chris Lattner
committed
const MachineOperand &MO = MI->getOperand(OpNo);
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
case 'a': // This is an address. Currently only 'i' and 'r' are expected.
if (MO.isImm()) {
O << MO.getImm();
return false;
if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) {
printSymbolOperand(MO);
return false;
}
O << '(';
printOperand(MI, OpNo);
O << ')';
return false;
}
return true;
case 'c': // Don't print "$" before a global var name or constant.
Chris Lattner
committed
if (MO.isImm())
O << MO.getImm();
else if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol())
printSymbolOperand(MO);
Chris Lattner
committed
else
Chris Lattner
committed
printOperand(MI, OpNo);
case 'A': // Print '*' before a register (it must be a register)
Chris Lattner
committed
if (MO.isReg()) {
O << '*';
printOperand(MI, OpNo);
return false;
}
return true;
case 'b': // Print QImode register
case 'h': // Print QImode high register
case 'w': // Print HImode register
case 'k': // Print SImode register
case 'q': // Print DImode register
Chris Lattner
committed
if (MO.isReg())
return printAsmMRegister(MO, ExtraCode[0]);
printOperand(MI, OpNo);
return false;
case 'P': // This is the operand of a call, treat specially.
print_pcrel_imm(MI, OpNo);
Chris Lattner
committed
case 'n': // Negate the immediate or print a '-' before the operand.
// Note: this is a temporary solution. It should be handled target
// independently as part of the 'MC' work.
if (MO.isImm()) {
O << -MO.getImm();
return false;
}
O << '-';
}
printOperand(MI, OpNo);
return false;
}
bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
case 'b': // Print QImode register
case 'h': // Print QImode high register
case 'w': // Print HImode register
case 'k': // Print SImode register
case 'q': // Print SImode register
// These only apply to registers, ignore on mem.
break;
case 'P': // Don't print @PLT, but do print as memory.
printMemReference(MI, OpNo, "no-rip");
return false;
}
}
printMemReference(MI, OpNo);
return false;
}
static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
// Convert registers in the addr mode according to subreg64.
for (unsigned i = 0; i != 4; ++i) {
if (!MI->getOperand(i).isReg()) continue;
unsigned Reg = MI->getOperand(i).getReg();
if (Reg == 0) continue;
Owen Anderson
committed
MI->getOperand(i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
}
}
Chris Lattner
committed
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
/// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
/// MCOperand.
MCOperand X86ATTAsmPrinter::LowerGlobalAddressOperand(const MachineOperand &MO){
const GlobalValue *GV = MO.getGlobal();
const char *Suffix = "";
if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
Suffix = "$stub";
else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
Suffix = "$non_lazy_ptr";
std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0');
if (Subtarget->isTargetCygMing())
DecorateCygMingName(Name, GV);
// Handle dllimport linkage.
if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
Name = "__imp_" + Name;
if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE)
GVStubs[Name] = Mang->getMangledName(GV);
else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY ||
MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
HiddenGVStubs[Name] = Mang->getMangledName(GV);
else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
FnStubs[Name] = Mang->getMangledName(GV);
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
// Handle target operand flags.
// FIXME: This should be common between external symbols, constant pool etc.
MCSymbol *NegatedSymbol = 0;
switch (MO.getTargetFlags()) {
default:
llvm_unreachable("Unknown target flag on GV operand");
case X86II::MO_NO_FLAG: // No flag.
break;
case X86II::MO_DARWIN_NONLAZY:
case X86II::MO_DARWIN_HIDDEN_NONLAZY:
case X86II::MO_DLLIMPORT:
case X86II::MO_DARWIN_STUB:
// These affect the name of the symbol, not any suffix.
break;
case X86II::MO_GOT_ABSOLUTE_ADDRESS:
assert(0 && "Reloc mode unimp!");
//O << " + [.-";
//PrintPICBaseSymbol();
//O << ']';
break;
case X86II::MO_PIC_BASE_OFFSET:
case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
// Subtract the pic base.
NegatedSymbol = GetPICBaseSymbol();
break;
// FIXME: These probably should be a modifier on the symbol or something??
case X86II::MO_TLSGD: Name += "@TLSGD"; break;
case X86II::MO_GOTTPOFF: Name += "@GOTTPOFF"; break;
case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
case X86II::MO_TPOFF: Name += "@TPOFF"; break;
case X86II::MO_NTPOFF: Name += "@NTPOFF"; break;
case X86II::MO_GOTPCREL: Name += "@GOTPCREL"; break;
case X86II::MO_GOT: Name += "@GOT"; break;
case X86II::MO_GOTOFF: Name += "@GOTOFF"; break;
case X86II::MO_PLT: Name += "@PLT"; break;
}
Chris Lattner
committed
// Create a symbol for the name.
MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name);
return MCOperand::CreateMCValue(MCValue::get(Sym, NegatedSymbol,
MO.getOffset()));
Chris Lattner
committed
}
MCOperand X86ATTAsmPrinter::
LowerExternalSymbolOperand(const MachineOperand &MO){
std::string Name = Mang->makeNameProper(MO.getSymbolName());
if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
FnStubs[Name+"$stub"] = Name;
Name += "$stub";
}
MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name);
return MCOperand::CreateMCValue(MCValue::get(Sym, 0, MO.getOffset()));
}
/// printMachineInstruction -- Print out a single X86 LLVM instruction MI in
/// AT&T syntax to the current output stream.
///
void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
if (!NewAsmPrinter) {
// Call the autogenerated instruction printer routines.
printInstruction(MI);
return;
}
MCInst TmpInst;
switch (MI->getOpcode()) {
case TargetInstrInfo::DBG_LABEL:
case TargetInstrInfo::EH_LABEL:
case TargetInstrInfo::GC_LABEL:
printLabel(MI);
return;
case TargetInstrInfo::INLINEASM:
O << '\t';
printInlineAsm(MI);
return;
case TargetInstrInfo::IMPLICIT_DEF:
printImplicitDef(MI);
return;
case X86::MOVPC32r: {
// This is a pseudo op for a two instruction sequence with a label, which
// looks like:
// call "L1$pb"
// "L1$pb":
// popl %esi
// Emit the call.
MCSymbol *PICBase = GetPICBaseSymbol();
TmpInst.setOpcode(X86::CALLpcrel32);
TmpInst.addOperand(MCOperand::CreateMCValue(MCValue::get(PICBase)));
printInstruction(&TmpInst);
// Emit the label.
OutStreamer.EmitLabel(PICBase);
// popl $reg
TmpInst.setOpcode(X86::POP32r);
TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
printInstruction(&TmpInst);
O << "OLD: ";
// Call the autogenerated instruction printer routines.
printInstruction(MI);
return;
}
}
O << "NEW: ";
TmpInst.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
MCOperand MCOp;
switch (MO.getType()) {
default:
O.flush();
errs() << "Cannot lower operand #" << i << " of :" << *MI;
llvm_unreachable("Unimp");
case MachineOperand::MO_Register:
MCOp = MCOperand::CreateReg(MO.getReg());
break;
case MachineOperand::MO_Immediate:
MCOp = MCOperand::CreateImm(MO.getImm());
break;
case MachineOperand::MO_MachineBasicBlock:
MCOp = MCOperand::CreateMBBLabel(getFunctionNumber(),
MO.getMBB()->getNumber());
break;
case MachineOperand::MO_GlobalAddress:
MCOp = LowerGlobalAddressOperand(MO);
break;
case MachineOperand::MO_ExternalSymbol:
MCOp = LowerExternalSymbolOperand(MO);
TmpInst.addOperand(MCOp);
}
switch (TmpInst.getOpcode()) {
case X86::LEA64_32r:
// Handle the 'subreg rewriting' for the lea64_32mem operand.
lower_lea64_32mem(&TmpInst, 1);
break;
// FIXME: Convert TmpInst.
printInstruction(&TmpInst);
O << "OLD: ";
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
void X86ATTAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
const TargetData *TD = TM.getTargetData();
if (!GVar->hasInitializer())
return; // External global require no code
// Check to see if this is a special global used by LLVM, if so, emit it.
if (EmitSpecialLLVMGlobal(GVar)) {
if (Subtarget->isTargetDarwin() &&
TM.getRelocationModel() == Reloc::Static) {
if (GVar->getName() == "llvm.global_ctors")
O << ".reference .constructors_used\n";
else if (GVar->getName() == "llvm.global_dtors")
O << ".reference .destructors_used\n";
return;
}
std::string name = Mang->getMangledName(GVar);
Constant *C = GVar->getInitializer();
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
Anton Korobeynikov
committed
printVisibility(name, GVar->getVisibility());
if (Subtarget->isTargetELF())
O << "\t.type\t" << name << ",@object\n";
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
const MCSection *TheSection =
getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
OutStreamer.SwitchSection(TheSection);
// FIXME: get this stuff from section kind flags.
if (C->isNullValue() && !GVar->hasSection() &&
// Don't put things that should go in the cstring section into "comm".
!TheSection->getKind().isMergeableCString()) {
if (GVar->hasExternalLinkage()) {
if (const char *Directive = MAI->getZeroFillDirective()) {
O << "\t.globl " << name << '\n';
O << Directive << "__DATA, __common, " << name << ", "
<< Size << ", " << Align << '\n';
if (!GVar->isThreadLocal() &&
(GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
if (MAI->getLCOMMDirective() != NULL) {
O << MAI->getLCOMMDirective() << name << ',' << Size;
if (Subtarget->isTargetDarwin())
O << ',' << Align;
} else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) {
O << "\t.globl " << name << '\n'
<< MAI->getWeakDefDirective() << name << '\n';
EmitAlignment(Align, GVar);
O << name << ":";
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << ' ';
WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
O << '\n';
EmitGlobalConstant(C);
return;
O << MAI->getCOMMDirective() << name << ',' << Size;
if (MAI->getCOMMDirectiveTakesAlignment())
O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
if (!Subtarget->isTargetCygMing()) {
O << "\t.local\t" << name << '\n';
O << MAI->getCOMMDirective() << name << ',' << Size;
if (MAI->getCOMMDirectiveTakesAlignment())
O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);