diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 096f712eba3..02faf7cdb39 100755 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -16,6 +16,7 @@ #define DEBUG_TYPE "asm-printer" #include "X86ATTAsmPrinter.h" #include "X86.h" +#include "X86COFF.h" #include "X86MachineFunctionInfo.h" #include "X86TargetMachine.h" #include "X86TargetAsmInfo.h" @@ -128,7 +129,17 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { if (F->hasHiddenVisibility()) if (const char *Directive = TAI->getHiddenDirective()) O << Directive << CurrentFnName << "\n"; - + + if (Subtarget->isTargetELF()) + O << "\t.type " << CurrentFnName << ",@function\n"; + else if (Subtarget->isTargetCygMing()) { + O << "\t.def\t " << CurrentFnName + << ";\t.scl\t" << + (F->getLinkage() == Function::InternalLinkage ? 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() && @@ -289,10 +300,16 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, } O << Name; - if (Subtarget->isPICStyleGOT() && isCallOp && isa(GV)) { - // Assemble call via PLT for non-local symbols - if (!isHidden || isExt) - O << "@PLT"; + if (isCallOp && isa(GV)) { + if (Subtarget->isPICStyleGOT()) { + // Assemble call via PLT for non-local symbols + if (!isHidden || GV->isExternal()) + O << "@PLT"; + } + if (Subtarget->isTargetCygMing() && GV->isExternal()) { + // Save function name for later type emission + FnStubs.insert(Name); + } } } diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 78b1af22e5b..767ab23ce3b 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -16,6 +16,7 @@ #include "X86AsmPrinter.h" #include "X86ATTAsmPrinter.h" +#include "X86COFF.h" #include "X86IntelAsmPrinter.h" #include "X86MachineFunctionInfo.h" #include "X86Subtarget.h" @@ -249,6 +250,9 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { if (I->hasHiddenVisibility()) if (const char *Directive = TAI->getHiddenDirective()) O << Directive << name << "\n"; + + if (Subtarget->isTargetELF()) + O << "\t.type " << name << ",@object\n"; } // Output linker support code for dllexported globals @@ -308,7 +312,19 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { // linker can safely perform dead code stripping. Since LLVM never // generates code that does this, it is always safe to set. O << "\t.subsections_via_symbols\n"; - } else if (Subtarget->isTargetELF() || Subtarget->isTargetCygMing()) { + } else if (Subtarget->isTargetCygMing()) { + // Emit type information for external functions + for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end(); + i != e; ++i) { + O << "\t.def\t " << *i + << ";\t.scl\t" << COFF::C_EXT + << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) + << ";\t.endef\n"; + } + + // Emit final debug information. + DW.EndModule(); + } else if (Subtarget->isTargetELF()) { // Emit final debug information. DW.EndModule(); } diff --git a/lib/Target/X86/X86COFF.h b/lib/Target/X86/X86COFF.h new file mode 100644 index 00000000000..1d7878b88b1 --- /dev/null +++ b/lib/Target/X86/X86COFF.h @@ -0,0 +1,89 @@ +//===--- X86COFF.h - Some definitions from COFF documentations ------------===// +// +// 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 just defines some symbols found in COFF documentation. They are +// used to emit function type information for COFF targets (Cygwin/Mingw32). +// +//===----------------------------------------------------------------------===// + +#ifndef X86COFF_H +#define X86COFF_H + +namespace COFF +{ +enum StorageClass { + C_EFCN = -1, // physical end of function + C_NULL = 0, + C_AUTO = 1, // external definition + C_EXT = 2, // external symbol + C_STAT = 3, // static + C_REG = 4, // register variable + C_EXTDEF = 5, // external definition + C_LABEL = 6, // label + C_ULABEL = 7, // undefined label + C_MOS = 8, // member of structure + C_ARG = 9, // function argument + C_STRTAG = 10, // structure tag + C_MOU = 11, // member of union + C_UNTAG = 12, // union tag + C_TPDEF = 13, // type definition + C_USTATIC = 14, // undefined static + C_ENTAG = 15, // enumeration tag + C_MOE = 16, // member of enumeration + C_REGPARM = 17, // register parameter + C_FIELD = 18, // bit field + + C_BLOCK = 100, // ".bb" or ".eb" + C_FCN = 101, // ".bf" or ".ef" + C_EOS = 102, // end of structure + C_FILE = 103, // file name + C_LINE = 104, // dummy class for line number entry + C_ALIAS = 105, // duplicate tag + C_HIDDEN = 106 +}; + +enum SymbolType { + T_NULL = 0, // no type info + T_ARG = 1, // function argument (only used by compiler) + T_VOID = 1, + T_CHAR = 2, // character + T_SHORT = 3, // short integer + T_INT = 4, // integer + T_LONG = 5, // long integer + T_FLOAT = 6, // floating point + T_DOUBLE = 7, // double word + T_STRUCT = 8, // structure + T_UNION = 9, // union + T_ENUM = 10, // enumeration + T_MOE = 11, // member of enumeration + T_UCHAR = 12, // unsigned character + T_USHORT = 13, // unsigned short + T_UINT = 14, // unsigned integer + T_ULONG = 15 // unsigned long +}; + +enum SymbolDerivedType { + DT_NON = 0, // no derived type + DT_PTR = 1, // pointer + DT_FCN = 2, // function + DT_ARY = 3 // array +}; + +enum TypePacking { + N_BTMASK = 017, + N_TMASK = 060, + N_TMASK1 = 0300, + N_TMASK2 = 0360, + N_BTSHFT = 4, + N_TSHIFT = 2 +}; + +} + +#endif // X86COFF_H