Adding dllimport, dllexport and external weak linkage types.
DLL* linkages got full (I hope) codegeneration support in C & both x86
assembler backends.
External weak linkage added for future use, we don't provide any
codegeneration, etc. support for it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30374 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp
index b17cde1..1ce24fd 100755
--- a/lib/Target/X86/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/X86ATTAsmPrinter.cpp
@@ -48,10 +48,13 @@
SwitchToTextSection(TAI->getTextSection(), F);
EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
break;
+ case Function::DLLExportLinkage:
+ DLLExportedFns.insert(Mang->makeNameProper(F->getName(), ""));
+ //FALLS THROUGH
case Function::ExternalLinkage:
SwitchToTextSection(TAI->getTextSection(), F);
EmitAlignment(4, F); // FIXME: This should be parameterized somewhere.
- O << "\t.globl\t" << CurrentFnName << "\n";
+ O << "\t.globl\t" << CurrentFnName << "\n";
break;
case Function::WeakLinkage:
case Function::LinkOnceLinkage:
@@ -179,8 +182,9 @@
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (!isMemOp && !isCallOp) O << '$';
- GlobalValue *GV = MO.getGlobal();
+ GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
+
bool isExt = (GV->isExternal() || GV->hasWeakLinkage() ||
GV->hasLinkOnceLinkage());
if (X86PICStyle == PICStyle::Stub &&
@@ -196,13 +200,27 @@
GVStubs.insert(Name);
O << "L" << Name << "$non_lazy_ptr";
}
- } else
+ } else {
+ if (GV->hasDLLImportLinkage()) {
+ // FIXME: This should be fixed with full support of stdcall & fastcall
+ // CC's
+ O << "__imp_";
+ }
O << Name;
+ }
+
if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
O << "-\"L" << getFunctionNumber() << "$pb\"";
- } else
+ } else {
+ if (GV->hasDLLImportLinkage()) {
+ // FIXME: This should be fixed with full support of stdcall & fastcall
+ // CC's
+ O << "__imp_";
+ }
O << Name;
-
+
+ }
+
int Offset = MO.getOffset();
if (Offset > 0)
O << "+" << Offset;
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index b634d13..08dc7b2 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -112,6 +112,9 @@
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::DLLExportLinkage:
+ DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),""));
+ // FALL THROUGH
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << "\t.globl " << name << "\n";
@@ -134,6 +137,27 @@
}
}
+ // Output linker support code for dllexported globals
+ if (DLLExportedGVs.begin() != DLLExportedGVs.end()) {
+ SwitchToDataSection(".section .drectve", 0);
+ }
+
+ for (std::set<std::string>::iterator i = DLLExportedGVs.begin(),
+ e = DLLExportedGVs.end();
+ i != e; ++i) {
+ O << "\t.ascii \" -export:" << *i << ",data\"\n";
+ }
+
+ if (DLLExportedFns.begin() != DLLExportedFns.end()) {
+ SwitchToDataSection(".section .drectve", 0);
+ }
+
+ for (std::set<std::string>::iterator i = DLLExportedFns.begin(),
+ e = DLLExportedFns.end();
+ i != e; ++i) {
+ O << "\t.ascii \" -export:" << *i << "\"\n";
+ }
+
if (Subtarget->isTargetDarwin()) {
SwitchToDataSection("", 0);
diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h
index 6db9e45..ae03ca5 100755
--- a/lib/Target/X86/X86AsmPrinter.h
+++ b/lib/Target/X86/X86AsmPrinter.h
@@ -63,6 +63,9 @@
// Necessary for Darwin to print out the apprioriate types of linker stubs
std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
+ // Necessary for dllexport support
+ std::set<std::string> DLLExportedFns, DLLExportedGVs;
+
inline static bool isScale(const MachineOperand &MO) {
return MO.isImmediate() &&
(MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index dfd7aa5..166345c 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1964,6 +1964,15 @@
(GV->isExternal() && !GV->hasNotBeenReadFromBytecode()));
}
+/// WinndowsGVRequiresExtraLoad - true if accessing the GV requires an extra
+/// load. For Windows, dllimported variables (not functions!) are indirect,
+/// loading the value at address GV rather then the value of GV itself. This
+/// means that the GlobalAddress must be in the base or index register of the
+/// address, not the GV offset field.
+static bool WindowsGVRequiresExtraLoad(GlobalValue *GV) {
+ return (isa<GlobalVariable>((Value*)GV) && GV->hasDLLImportLinkage());
+}
+
/// isUndefOrInRange - Op is either an undef node or a ConstantSDNode. Return
/// true if Op is undef or if its value falls within the specified range (L, H].
static bool isUndefOrInRange(SDOperand Op, unsigned Low, unsigned Hi) {
@@ -3376,7 +3385,14 @@
DarwinGVRequiresExtraLoad(GV))
Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(),
Result, DAG.getSrcValue(NULL));
+ } else if (Subtarget->isTargetCygwin() || Subtarget->isTargetWindows()) {
+ // FIXME: What's about PIC?
+ if (WindowsGVRequiresExtraLoad(GV)) {
+ Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(),
+ Result, DAG.getSrcValue(NULL));
+ }
}
+
return Result;
}
diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp
index 24dbb15..44a218c 100755
--- a/lib/Target/X86/X86IntelAsmPrinter.cpp
+++ b/lib/Target/X86/X86IntelAsmPrinter.cpp
@@ -35,10 +35,23 @@
EmitConstantPool(MF.getConstantPool());
// Print out labels for the function.
- SwitchToTextSection("_text", MF.getFunction());
- EmitAlignment(4);
- if (MF.getFunction()->getLinkage() == GlobalValue::ExternalLinkage)
+ const Function* F = MF.getFunction();
+ switch (F->getLinkage()) {
+ default: assert(0 && "Unsupported linkage type!");
+ case Function::InternalLinkage:
+ SwitchToTextSection("_text", F);
+ EmitAlignment(4);
+ break;
+ case Function::DLLExportLinkage:
+ DLLExportedFns.insert(CurrentFnName);
+ //FALLS THROUGH
+ case Function::ExternalLinkage:
O << "\tpublic " << CurrentFnName << "\n";
+ SwitchToTextSection("_text", F);
+ EmitAlignment(4);
+ break;
+ }
+
O << CurrentFnName << "\tproc near\n";
// Print out code for the function.
@@ -118,8 +131,15 @@
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
+ GlobalValue *GV = MO.getGlobal();
+
if (!isMemOp && !isCallOp) O << "OFFSET ";
- O << Mang->getValueName(MO.getGlobal());
+ if (GV->hasDLLImportLinkage()) {
+ // FIXME: This should be fixed with full support of stdcall & fastcall
+ // CC's
+ O << "__imp_";
+ }
+ O << Mang->getValueName(GV);
int Offset = MO.getOffset();
if (Offset > 0)
O << " + " << Offset;
@@ -350,6 +370,9 @@
// FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
// are also available.
break;
+ case GlobalValue::DLLExportLinkage:
+ DLLExportedGVs.insert(name);
+ // FALL THROUGH
case GlobalValue::ExternalLinkage:
O << "\tpublic " << name << "\n";
// FALL THROUGH
@@ -371,6 +394,34 @@
if (bCustomSegment)
O << name << "?\tends\n";
}
+
+ // Output linker support code for dllexported globals
+ if ((DLLExportedGVs.begin() != DLLExportedGVs.end()) ||
+ (DLLExportedFns.begin() != DLLExportedFns.end())) {
+ SwitchToDataSection("", 0);
+ O << "; WARNING: The following code is valid only with MASM v8.x and (possible) higher\n"
+ << "; This version of MASM is usually shipped with Microsoft Visual Studio 2005\n"
+ << "; or (possible) further versions. Unfortunately, there is no way to support\n"
+ << "; dllexported symbols in the earlier versions of MASM in fully automatic way\n\n";
+ O << "_drectve\t segment info alias('.drectve')\n";
+ }
+
+ for (std::set<std::string>::iterator i = DLLExportedGVs.begin(),
+ e = DLLExportedGVs.end();
+ i != e; ++i) {
+ O << "\t db ' /EXPORT:" << *i << ",data'\n";
+ }
+
+ for (std::set<std::string>::iterator i = DLLExportedFns.begin(),
+ e = DLLExportedFns.end();
+ i != e; ++i) {
+ O << "\t db ' /EXPORT:" << *i << "'\n";
+ }
+
+ if ((DLLExportedGVs.begin() != DLLExportedGVs.end()) ||
+ (DLLExportedFns.begin() != DLLExportedFns.end())) {
+ O << "_drectve\t ends\n";
+ }
// Bypass X86SharedAsmPrinter::doFinalization().
AsmPrinter::doFinalization(M);
diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h
index 224ebcd..6e0d1db 100644
--- a/lib/Target/X86/X86Subtarget.h
+++ b/lib/Target/X86/X86Subtarget.h
@@ -99,6 +99,8 @@
bool isTargetDarwin() const { return TargetType == isDarwin; }
bool isTargetELF() const { return TargetType == isELF; }
+ bool isTargetWindows() const { return TargetType == isWindows; }
+ bool isTargetCygwin() const { return TargetType == isCygwin; }
};
} // End llvm namespace