mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
Darwin ABI issues: weak, linkonce, etc. dynamic-no-pic support is complete.
Also fixed a function stub bug. Added weak and linkonce support for x86 Linux. llvm-svn: 26038
This commit is contained in:
parent
a7d31e53e8
commit
15369d0b89
@ -33,12 +33,32 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
EmitConstantPool(MF.getConstantPool());
|
||||
|
||||
// Print out labels for the function.
|
||||
SwitchSection("\t.text\n", MF.getFunction());
|
||||
EmitAlignment(4); // FIXME: This should be parameterized somewhere.
|
||||
if (!MF.getFunction()->hasInternalLinkage())
|
||||
const Function *F = MF.getFunction();
|
||||
switch (F->getLinkage()) {
|
||||
default: assert(0 && "Unknown linkage type!");
|
||||
case Function::InternalLinkage: // Symbols default to internal.
|
||||
SwitchSection(".text", F);
|
||||
EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
|
||||
break;
|
||||
case Function::ExternalLinkage:
|
||||
SwitchSection(".text", F);
|
||||
EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
|
||||
O << "\t.globl\t" << CurrentFnName << "\n";
|
||||
if (HasDotTypeDotSizeDirective)
|
||||
O << "\t.type\t" << CurrentFnName << ", @function\n";
|
||||
break;
|
||||
case Function::WeakLinkage:
|
||||
case Function::LinkOnceLinkage:
|
||||
if (forDarwin) {
|
||||
SwitchSection(".section __TEXT,__textcoal_nt,coalesced,pure_instructions",
|
||||
F);
|
||||
O << "\t.weak_definition\t" << CurrentFnName << "\n";
|
||||
} else {
|
||||
EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
|
||||
O << "\t.section\t.llvm.linkonce.t." << CurrentFnName
|
||||
<< ",\"ax\",@progbits\n";
|
||||
O << "\t.weak " << CurrentFnName << "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
O << CurrentFnName << ":\n";
|
||||
|
||||
// Print out code for the function.
|
||||
@ -95,27 +115,24 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||
// Darwin block shameless ripped from PowerPCAsmPrinter.cpp
|
||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||
// Darwin block shameless ripped from PPCAsmPrinter.cpp
|
||||
if (forDarwin) {
|
||||
if (!isCallOp) O << '$';
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
GlobalValue *GV = MO.getGlobal();
|
||||
std::string Name = Mang->getValueName(GV);
|
||||
|
||||
// Dynamically-resolved functions need a stub for the function. Be
|
||||
// wary however not to output $stub for external functions whose addresses
|
||||
// are taken. Those should be emitted as $non_lazy_ptr below.
|
||||
Function *F = dyn_cast<Function>(GV);
|
||||
if (F && isCallOp && F->isExternal()) {
|
||||
FnStubs.insert(Name);
|
||||
O << "L" << Name << "$stub";
|
||||
} else if (GV->hasLinkOnceLinkage()) {
|
||||
// Link-once, External, or Weakly-linked global variables need
|
||||
// non-lazily-resolved stubs
|
||||
LinkOnceStubs.insert(Name);
|
||||
O << "L" << Name << "$non_lazy_ptr";
|
||||
} else if (GV->isExternal() || GV->hasWeakLinkage()) {
|
||||
if (GV->isExternal() || GV->hasWeakLinkage() ||
|
||||
GV->hasLinkOnceLinkage()) {
|
||||
// Dynamically-resolved functions need a stub for the function.
|
||||
if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) {
|
||||
FnStubs.insert(Name);
|
||||
O << "L" << Name << "$stub";
|
||||
} else {
|
||||
GVStubs.insert(Name);
|
||||
O << "L" << Name << "$non_lazy_ptr";
|
||||
}
|
||||
} else {
|
||||
O << Mang->getValueName(GV);
|
||||
}
|
||||
@ -126,7 +143,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
O << Offset;
|
||||
return;
|
||||
}
|
||||
if (!isCallOp) O << '$';
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
int Offset = MO.getOffset();
|
||||
if (Offset > 0)
|
||||
@ -137,13 +154,14 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
}
|
||||
case MachineOperand::MO_ExternalSymbol: {
|
||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||
if (isCallOp && forDarwin) {
|
||||
std::string Name(GlobalPrefix); Name += MO.getSymbolName();
|
||||
FnStubs.insert(Name);
|
||||
O << "L" << Name << "$stub";
|
||||
return;
|
||||
}
|
||||
if (!isCallOp) O << '$';
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
O << GlobalPrefix << MO.getSymbolName();
|
||||
return;
|
||||
}
|
||||
@ -197,7 +215,7 @@ void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
}
|
||||
|
||||
if (DispSpec.isGlobalAddress()) {
|
||||
printOperand(MI, Op+3, "call");
|
||||
printOperand(MI, Op+3, "mem");
|
||||
} else {
|
||||
int DispVal = DispSpec.getImmedValue();
|
||||
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
|
||||
|
@ -80,113 +80,93 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
// Print out module-level global variables here.
|
||||
for (Module::const_global_iterator I = M.global_begin(),
|
||||
E = M.global_end(); I != E; ++I) {
|
||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||
I != E; ++I) {
|
||||
if (!I->hasInitializer()) continue; // External global require no code
|
||||
|
||||
// Check to see if this is a special global used by LLVM, if so, emit it.
|
||||
if (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I))
|
||||
continue;
|
||||
|
||||
O << "\n\n";
|
||||
std::string name = Mang->getValueName(I);
|
||||
Constant *C = I->getInitializer();
|
||||
unsigned Size = TD.getTypeSize(C->getType());
|
||||
unsigned Align = getPreferredAlignmentLog(I);
|
||||
|
||||
switch (I->getLinkage()) {
|
||||
default: assert(0 && "Unknown linkage type!");
|
||||
case GlobalValue::LinkOnceLinkage:
|
||||
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
|
||||
if (C->isNullValue()) {
|
||||
O << COMMDirective << name << "," << Size;
|
||||
if (COMMDirectiveTakesAlignment)
|
||||
O << "," << (1 << Align);
|
||||
O << "\t\t" << CommentString << " " << I->getName() << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Nonnull linkonce -> weak
|
||||
O << "\t.weak " << name << "\n";
|
||||
O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
|
||||
SwitchSection("", I);
|
||||
break;
|
||||
case GlobalValue::InternalLinkage:
|
||||
if (C->isNullValue()) {
|
||||
if (LCOMMDirective) {
|
||||
O << LCOMMDirective << name << "," << Size << "," << Align;
|
||||
continue;
|
||||
} else {
|
||||
SwitchSection(".bss", I);
|
||||
O << "\t.local " << name << "\n";
|
||||
O << COMMDirective << name << "," << Size;
|
||||
if (COMMDirectiveTakesAlignment)
|
||||
O << "," << (1 << Align);
|
||||
O << "\t\t# ";
|
||||
WriteAsOperand(O, I, true, true, &M);
|
||||
O << "\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (C->isNullValue() && /* FIXME: Verify correct */
|
||||
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
||||
I->hasLinkOnceLinkage())) {
|
||||
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
|
||||
if (forDarwin) {
|
||||
SwitchSection(".data", I);
|
||||
if (I->hasInternalLinkage())
|
||||
O << LCOMMDirective << name << "," << Size << "," << Align;
|
||||
else
|
||||
O << COMMDirective << name << "," << Size;
|
||||
} else {
|
||||
SwitchSection(".local", I);
|
||||
O << COMMDirective << name << "," << Size << "," << Align;
|
||||
}
|
||||
O << "\t\t" << CommentString << " '" << I->getName() << "'\n";
|
||||
} else {
|
||||
switch (I->getLinkage()) {
|
||||
case GlobalValue::LinkOnceLinkage:
|
||||
case GlobalValue::WeakLinkage:
|
||||
if (forDarwin) {
|
||||
O << "\t.globl " << name << '\n'
|
||||
<< "\t.weak_definition " << name << '\n';
|
||||
SwitchSection(".section __DATA,__datacoal_nt,coalesced", I);
|
||||
} else {
|
||||
O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
|
||||
O << "\t.weak " << name << "\n";
|
||||
}
|
||||
break;
|
||||
case GlobalValue::AppendingLinkage:
|
||||
// FIXME: appending linkage variables should go into a section of
|
||||
// their name or something. For now, just emit them as external.
|
||||
case GlobalValue::ExternalLinkage:
|
||||
SwitchSection(C->isNullValue() ? ".bss" : ".data", I);
|
||||
// If external or appending, declare as a global symbol
|
||||
O << "\t.globl " << name << "\n";
|
||||
// FALL THROUGH
|
||||
case GlobalValue::InternalLinkage:
|
||||
SwitchSection(".data", I);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Unknown linkage type!");
|
||||
}
|
||||
|
||||
EmitAlignment(Align);
|
||||
if (HasDotTypeDotSizeDirective) {
|
||||
O << "\t.type " << name << ",@object\n";
|
||||
O << "\t.size " << name << "," << Size << "\n";
|
||||
}
|
||||
O << name << ":\t\t\t" << CommentString << ' ' << I->getName() << '\n';
|
||||
EmitAlignment(Align, I);
|
||||
O << name << ":\t\t\t\t" << CommentString << " '" << I->getName()
|
||||
<< "'\n";
|
||||
EmitGlobalConstant(C);
|
||||
O << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (forDarwin) {
|
||||
SwitchSection("", 0);
|
||||
// Output stubs for external global variables
|
||||
if (GVStubs.begin() != GVStubs.end())
|
||||
O << "\t.non_lazy_symbol_pointer\n";
|
||||
for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
|
||||
i != e; ++i) {
|
||||
O << "L" << *i << "$non_lazy_ptr:\n";
|
||||
O << "\t.indirect_symbol " << *i << "\n";
|
||||
O << "\t.long\t0\n";
|
||||
}
|
||||
|
||||
// Output stubs for dynamically-linked functions
|
||||
unsigned j = 1;
|
||||
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
|
||||
i != e; ++i, ++j) {
|
||||
O << "\t.symbol_stub\n";
|
||||
SwitchSection(".section __IMPORT,__jump_table,symbol_stubs,"
|
||||
"self_modifying_code+pure_instructions,5", 0);
|
||||
O << "L" << *i << "$stub:\n";
|
||||
O << "\t.indirect_symbol " << *i << "\n";
|
||||
O << "\tjmp\t*L" << j << "$lz\n";
|
||||
O << "L" << *i << "$stub_binder:\n";
|
||||
O << "\tpushl\t$L" << j << "$lz\n";
|
||||
O << "\tjmp\tdyld_stub_binding_helper\n";
|
||||
O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n";
|
||||
O << "L" << j << "$lz:\n";
|
||||
O << "\t.indirect_symbol " << *i << "\n";
|
||||
O << "\t.long\tL" << *i << "$stub_binder\n";
|
||||
O << "\thlt ; hlt ; hlt ; hlt ; hlt\n";
|
||||
}
|
||||
|
||||
O << "\n";
|
||||
|
||||
// Output stubs for link-once variables
|
||||
if (LinkOnceStubs.begin() != LinkOnceStubs.end())
|
||||
O << ".data\n.align 2\n";
|
||||
for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
|
||||
e = LinkOnceStubs.end(); i != e; ++i) {
|
||||
O << "L" << *i << "$non_lazy_ptr:\n"
|
||||
<< "\t.long\t" << *i << '\n';
|
||||
// Output stubs for external and common global variables.
|
||||
if (GVStubs.begin() != GVStubs.end())
|
||||
SwitchSection(".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0);
|
||||
for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
|
||||
i != e; ++i) {
|
||||
O << "L" << *i << "$non_lazy_ptr:\n";
|
||||
O << "\t.indirect_symbol " << *i << "\n";
|
||||
O << "\t.long\t0\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1876,11 +1876,13 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
// the GlobalAddress must be in the base or index register of the address,
|
||||
// not the GV offset field.
|
||||
if (getTargetMachine().
|
||||
getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals() &&
|
||||
(GV->hasWeakLinkage() || GV->isExternal()))
|
||||
getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals()) {
|
||||
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
|
||||
(GV->isExternal() && !GV->hasNotBeenReadFromBytecode()))
|
||||
Result = DAG.getLoad(MVT::i32, DAG.getEntryNode(),
|
||||
DAG.getTargetGlobalAddress(GV, getPointerTy()),
|
||||
DAG.getSrcValue(NULL));
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
case ISD::VASTART: {
|
||||
|
@ -109,7 +109,7 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
|
||||
abort ();
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
if (!Modifier || strcmp(Modifier, "call"))
|
||||
if (!Modifier || strcmp(Modifier, "call") || strcmp(Modifier, "mem"))
|
||||
O << "OFFSET ";
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
int Offset = MO.getOffset();
|
||||
@ -161,7 +161,7 @@ void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
O << "[";
|
||||
bool NeedPlus = false;
|
||||
if (BaseReg.getReg()) {
|
||||
printOp(BaseReg, "call");
|
||||
printOp(BaseReg, "mem");
|
||||
NeedPlus = true;
|
||||
}
|
||||
|
||||
@ -176,7 +176,7 @@ void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
if (DispSpec.isGlobalAddress()) {
|
||||
if (NeedPlus)
|
||||
O << " + ";
|
||||
printOp(DispSpec, "call");
|
||||
printOp(DispSpec, "mem");
|
||||
} else {
|
||||
int DispVal = DispSpec.getImmedValue();
|
||||
if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) {
|
||||
|
Loading…
Reference in New Issue
Block a user