#include "llvm/Type.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
Ty = cast<PointerType>(Ty)->getElementType();
// Size should be aligned to DWORD boundary
- Size += ((TD->getABITypeSize(Ty) + 3)/4)*4;
+ Size += ((TD->getTypeAllocSize(Ty) + 3)/4)*4;
}
// We're not supporting tooooo huge arguments :)
}
/// PrintUnmangledNameSafely - Print out the printable characters in the name.
-/// Don't print things like \n or \0.
+/// Don't print things like \\n or \\0.
static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
Name != E; ++Name)
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
case Function::InternalLinkage: // Symbols default to internal.
+ case Function::PrivateLinkage:
EmitAlignment(FnAlign, F);
break;
case Function::DLLExportLinkage:
EmitAlignment(FnAlign, F);
O << "\t.globl\t" << CurrentFnName << '\n';
break;
- case Function::LinkOnceLinkage:
- case Function::WeakLinkage:
+ case Function::LinkOnceAnyLinkage:
+ case Function::LinkOnceODRLinkage:
+ case Function::WeakAnyLinkage:
+ case Function::WeakODRLinkage:
EmitAlignment(FnAlign, F);
if (Subtarget->isTargetDarwin()) {
O << "\t.globl\t" << CurrentFnName << '\n';
else if (Subtarget->isTargetCygMing()) {
O << "\t.def\t " << CurrentFnName
<< ";\t.scl\t" <<
- (F->getLinkage() == Function::InternalLinkage ? COFF::C_STAT : COFF::C_EXT)
+ (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT)
<< ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
<< ";\t.endef\n";
}
O << CurrentFnName << ":\n";
// Add some workaround for linkonce linkage on Cygwin\MinGW
if (Subtarget->isTargetCygMing() &&
- (F->getLinkage() == Function::LinkOnceLinkage ||
- F->getLinkage() == Function::WeakLinkage))
+ (F->hasLinkOnceLinkage() || F->hasWeakLinkage()))
O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n";
}
///
bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
const Function *F = MF.getFunction();
+ this->MF = &MF;
unsigned CC = F->getCallingConv();
SetupMachineFunction(MF);
// Emit pre-function debug and/or EH information.
if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- DW.BeginFunction(&MF);
+ DW->BeginFunction(&MF);
// 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 (!I->pred_empty()) {
- printBasicBlockLabel(I, true, true);
+ 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();
// Emit post-function debug information.
if (TAI->doesSupportDebugInformation())
- DW.EndFunction(&MF);
+ DW->EndFunction(&MF);
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
}
case MachineOperand::MO_Immediate:
- if (!Modifier ||
- (strcmp(Modifier, "debug") && strcmp(Modifier, "mem")))
+ if (!Modifier || (strcmp(Modifier, "debug") &&
+ strcmp(Modifier, "mem") &&
+ strcmp(Modifier, "call")))
O << '$';
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
+ printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
return;
case MachineOperand::MO_JumpTableIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (shouldPrintStub(TM, Subtarget)) {
// Link-once, declaration, or Weakly-linked global variables need
// non-lazily-resolved stubs
- if (GV->isDeclaration() || GV->mayBeOverridden()) {
+ if (GV->isDeclaration() || GV->isWeakForLinker()) {
// Dynamically-resolved functions need a stub for the function.
if (isCallOp && isa<Function>(GV)) {
// Function stubs are no longer needed for Mac OS X 10.5 and up.
FnStubs.insert(Name);
printSuffixedName(Name, "$stub");
}
+ } else if (GV->hasHiddenVisibility()) {
+ if (!GV->isDeclaration() && !GV->hasCommonLinkage())
+ // Definition is not definitely in the current translation unit.
+ O << Name;
+ else {
+ HiddenGVStubs.insert(Name);
+ printSuffixedName(Name, "$non_lazy_ptr");
+ }
} else {
GVStubs.insert(Name);
printSuffixedName(Name, "$non_lazy_ptr");
if (shouldPrintPLT(TM, Subtarget)) {
// Assemble call via PLT for externally visible symbols
if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
- !GV->hasInternalLinkage())
+ !GV->hasLocalLinkage())
O << "@PLT";
}
if (Subtarget->isTargetCygMing() && GV->isDeclaration())
printOffset(MO.getOffset());
if (isThreadLocal) {
- if (TM.getRelocationModel() == Reloc::PIC_ || Subtarget->is64Bit())
- O << "@TLSGD"; // general dynamic TLS model
- else
- if (GV->isDeclaration())
- O << "@INDNTPOFF"; // initial exec TLS model
+ TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
+ switch (model) {
+ case TLSModel::GeneralDynamic:
+ O << "@TLSGD";
+ break;
+ case TLSModel::LocalDynamic:
+ // O << "@TLSLD"; // local dynamic not implemented
+ O << "@TLSGD";
+ break;
+ case TLSModel::InitialExec:
+ if (Subtarget->is64Bit()) {
+ assert (!NotRIPRel);
+ O << "@GOTTPOFF(%rip)";
+ } else {
+ O << "@INDNTPOFF";
+ }
+ break;
+ case TLSModel::LocalExec:
+ if (Subtarget->is64Bit())
+ O << "@TPOFF";
else
- O << "@NTPOFF"; // local exec TLS model
+ O << "@NTPOFF";
+ break;
+ default:
+ assert (0 && "Unknown TLS model");
+ }
} else if (isMemOp) {
if (shouldPrintGOT(TM, Subtarget)) {
if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
O << "@GOT";
else
O << "@GOTOFF";
- } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel &&
- TM.getRelocationModel() != Reloc::Static) {
- if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
- O << "@GOTPCREL";
-
- if (needCloseParen) {
- needCloseParen = false;
- O << ')';
+ } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
+ if (TM.getRelocationModel() != Reloc::Static) {
+ if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
+ O << "@GOTPCREL";
+
+ if (needCloseParen) {
+ needCloseParen = false;
+ O << ')';
+ }
}
// Use rip when possible to reduce code size, except when
}
case MachineOperand::MO_ExternalSymbol: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
+ bool isMemOp = Modifier && !strcmp(Modifier, "mem");
bool needCloseParen = false;
std::string Name(TAI->getGlobalPrefix());
Name += MO.getSymbolName();
printSuffixedName(Name, "$stub");
return;
}
- if (!isCallOp)
+ if (!isMemOp && !isCallOp)
O << '$';
else if (Name[0] == '$') {
// The name begins with a dollar-sign. In order to avoid having it look
}
}
-void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier){
- assert(isMem(MI, Op) && "Invalid memory reference!");
+void X86ATTAsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op,
+ const char *Modifier,
+ bool NotRIPRel) {
MachineOperand BaseReg = MI->getOperand(Op);
MachineOperand IndexReg = MI->getOperand(Op+2);
const MachineOperand &DispSpec = MI->getOperand(Op+3);
- bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg();
+ NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
if (DispSpec.isGlobal() ||
DispSpec.isCPI() ||
- DispSpec.isJTI()) {
+ DispSpec.isJTI() ||
+ DispSpec.isSymbol()) {
printOperand(MI, Op+3, "mem", NotRIPRel);
} else {
int DispVal = DispSpec.getImm();
}
}
+void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
+ const char *Modifier, bool NotRIPRel){
+ assert(isMem(MI, Op) && "Invalid memory reference!");
+ MachineOperand Segment = MI->getOperand(Op+4);
+ if (Segment.getReg()) {
+ printOperand(MI, Op+4, Modifier);
+ O << ':';
+ }
+ printLeaMemReference(MI, Op, Modifier, NotRIPRel);
+}
+
void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
const MachineBasicBlock *MBB) const {
if (!TAI->getSetDirective())
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
case 'c': // Don't print "$" before a global var name or constant.
- printOperand(MI, OpNo, "mem");
+ printOperand(MI, OpNo, "mem", /*NotRIPRel=*/true);
return false;
case 'b': // Print QImode register
case 'h': // Print QImode high register
return false;
case 'P': // Don't print @PLT, but do print as memory.
- printOperand(MI, OpNo, "mem");
+ printOperand(MI, OpNo, "mem", /*NotRIPRel=*/true);
return false;
}
}
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, "mem", /*NotRIPRel=*/true);
+ return false;
}
}
printMemReference(MI, OpNo);
return false;
}
-/// printMachineInstruction -- Print out a single X86 LLVM instruction
-/// MI in AT&T syntax to the current output stream.
+/// 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;
/// doInitialization
bool X86ATTAsmPrinter::doInitialization(Module &M) {
- if (TAI->doesSupportDebugInformation()) {
- // Emit initial debug information.
- DW.BeginModule(&M);
- }
bool Result = AsmPrinter::doInitialization(M);
// Let PassManager know we need debug information and relay
// the MachineModuleInfo address on to DwarfWriter.
// AsmPrinter::doInitialization did this analysis.
- MMI = getAnalysisToUpdate<MachineModuleInfo>();
- DW.SetModuleInfo(MMI);
+ MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+ DW = getAnalysisIfAvailable<DwarfWriter>();
+ DW->BeginModule(&M, MMI, O, this, TAI);
}
// Darwin wants symbols to be quoted if they have complex names.
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
const Type *Type = C->getType();
- unsigned Size = TD->getABITypeSize(Type);
+ unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
printVisibility(name, GVar->getVisibility());
SwitchToSection(TAI->SectionForGlobal(GVar));
- if (C->isNullValue() && !GVar->hasSection()) {
+ if (C->isNullValue() && !GVar->hasSection() &&
+ !(Subtarget->isTargetDarwin() &&
+ TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) {
// FIXME: This seems to be pretty darwin-specific
if (GVar->hasExternalLinkage()) {
if (const char *Directive = TAI->getZeroFillDirective()) {
}
if (!GVar->isThreadLocal() &&
- (GVar->hasInternalLinkage() || GVar->mayBeOverridden())) {
+ (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
if (TAI->getLCOMMDirective() != NULL) {
- if (GVar->hasInternalLinkage()) {
+ if (GVar->hasLocalLinkage()) {
O << TAI->getLCOMMDirective() << name << ',' << Size;
if (Subtarget->isTargetDarwin())
O << ',' << Align;
O << "\t.globl " << name << '\n'
<< TAI->getWeakDefDirective() << name << '\n';
EmitAlignment(Align, GVar);
- O << name << ":\t\t\t\t" << TAI->getCommentString() << ' ';
- PrintUnmangledNameSafely(GVar, O);
+ O << name << ":";
+ if (VerboseAsm) {
+ O << "\t\t\t\t" << TAI->getCommentString() << ' ';
+ PrintUnmangledNameSafely(GVar, O);
+ }
O << '\n';
EmitGlobalConstant(C);
return;
}
} else {
if (!Subtarget->isTargetCygMing()) {
- if (GVar->hasInternalLinkage())
+ if (GVar->hasLocalLinkage())
O << "\t.local\t" << name << '\n';
}
O << TAI->getCOMMDirective() << name << ',' << Size;
if (TAI->getCOMMDirectiveTakesAlignment())
O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
}
- O << "\t\t" << TAI->getCommentString() << ' ';
- PrintUnmangledNameSafely(GVar, O);
+ if (VerboseAsm) {
+ O << "\t\t" << TAI->getCommentString() << ' ';
+ PrintUnmangledNameSafely(GVar, O);
+ }
O << '\n';
return;
}
switch (GVar->getLinkage()) {
case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceLinkage:
- case GlobalValue::WeakLinkage:
+ case GlobalValue::LinkOnceAnyLinkage:
+ case GlobalValue::LinkOnceODRLinkage:
+ case GlobalValue::WeakAnyLinkage:
+ case GlobalValue::WeakODRLinkage:
if (Subtarget->isTargetDarwin()) {
O << "\t.globl " << name << '\n'
<< TAI->getWeakDefDirective() << name << '\n';
// If external or appending, declare as a global symbol
O << "\t.globl " << name << '\n';
// FALL THROUGH
+ case GlobalValue::PrivateLinkage:
case GlobalValue::InternalLinkage:
break;
default:
}
EmitAlignment(Align, GVar);
- O << name << ":\t\t\t\t" << TAI->getCommentString() << ' ';
- PrintUnmangledNameSafely(GVar, O);
+ O << name << ":";
+ if (VerboseAsm){
+ O << "\t\t\t\t" << TAI->getCommentString() << ' ';
+ PrintUnmangledNameSafely(GVar, O);
+ }
O << '\n';
if (TAI->hasDotTypeDotSizeDirective())
O << "\t.size\t" << name << ", " << Size << '\n';
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
EmitGlobalConstant(C);
}
O << GV << "\n\t.long\t0\n";
}
+/// printHiddenGVStub - Print stub for a hidden global value.
+///
+void X86ATTAsmPrinter::printHiddenGVStub(const char *GV, const char *Prefix) {
+ EmitAlignment(2);
+ printSuffixedName(GV, "$non_lazy_ptr", Prefix);
+ if (Prefix) O << Prefix;
+ O << ":\n" << TAI->getData32bitsDirective() << GV << '\n';
+}
+
bool X86ATTAsmPrinter::doFinalization(Module &M) {
// Print out module-level global variables here.
if (I->hasDLLExportLinkage())
DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),""));
+
+ // If the global is a extern weak symbol, remember to emit the weak
+ // reference!
+ // FIXME: This is rather hacky, since we'll emit references to ALL weak stuff,
+ // not used. But currently it's the only way to deal with extern weak
+ // initializers hidden deep inside constant expressions.
+ if (I->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(I);
+ }
+
+ for (Module::const_iterator I = M.begin(), E = M.end();
+ I != E; ++I) {
+ // If the global is a extern weak symbol, remember to emit the weak
+ // reference!
+ // FIXME: This is rather hacky, since we'll emit references to ALL weak stuff,
+ // not used. But currently it's the only way to deal with extern weak
+ // initializers hidden deep inside constant expressions.
+ if (I->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(I);
}
// Output linker support code for dllexported globals
SwitchToDataSection("");
// Output stubs for dynamically-linked functions
- unsigned j = 1;
for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
- i != e; ++i, ++j) {
+ i != e; ++i) {
SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs,"
"self_modifying_code+pure_instructions,5", 0);
const char *p = i->getKeyData();
i != e; ++i)
printGVStub(i->getKeyData());
+ if (!HiddenGVStubs.empty()) {
+ SwitchToSection(TAI->getDataSection());
+ for (StringSet<>::iterator i = HiddenGVStubs.begin(), e = HiddenGVStubs.end();
+ i != e; ++i)
+ printHiddenGVStub(i->getKeyData());
+ }
+
// Emit final debug information.
- DW.EndModule();
+ DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
+ DW->EndModule();
// Funny Darwin hack: This flag tells the linker that no global symbols
// contain code that falls through to other global symbols (e.g. the obvious
}
// Emit final debug information.
- DW.EndModule();
+ DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
+ DW->EndModule();
} else if (Subtarget->isTargetELF()) {
// Emit final debug information.
- DW.EndModule();
+ DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
+ DW->EndModule();
}
return AsmPrinter::doFinalization(M);