//===----------------------------------------------------------------------===//
#include "X86IntelAsmPrinter.h"
+#include "X86TargetAsmInfo.h"
#include "X86.h"
+#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/Mangler.h"
+#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
-X86IntelAsmPrinter::X86IntelAsmPrinter(std::ostream &O, X86TargetMachine &TM)
- : X86SharedAsmPrinter(O, TM) {
+std::string X86IntelAsmPrinter::getSectionForFunction(const Function &F) const {
+ // Intel asm always emits functions to _text.
+ return "_text";
}
/// runOnMachineFunction - This uses the printMachineInstruction()
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();
+ unsigned CC = F->getCallingConv();
+
+ // 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<X86FunctionInfo>();
+
+ X86SharedAsmPrinter::decorateName(CurrentFnName, F);
+
+ SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
+
+ switch (F->getLinkage()) {
+ default: assert(0 && "Unsupported linkage type!");
+ case Function::InternalLinkage:
+ EmitAlignment(4);
+ break;
+ case Function::DLLExportLinkage:
+ DLLExportedFns.insert(CurrentFnName);
+ //FALLS THROUGH
+ case Function::ExternalLinkage:
O << "\tpublic " << CurrentFnName << "\n";
+ EmitAlignment(4);
+ break;
+ }
+
O << CurrentFnName << "\tproc near\n";
// Print out code for the function.
}
}
+ // Print out jump tables referenced by the function.
+ EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
+
O << CurrentFnName << "\tendp\n";
// We didn't modify anything.
case MachineOperand::MO_Register:
if (MRegisterInfo::isPhysicalRegister(MO.getReg())) {
unsigned Reg = MO.getReg();
- if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
- MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
- ? MVT::i16 : MVT::i8;
+ if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
+ MVT::ValueType VT = (strcmp(Modifier,"subreg64") == 0) ?
+ MVT::i64 : ((strcmp(Modifier, "subreg32") == 0) ? MVT::i32 :
+ ((strcmp(Modifier,"subreg16") == 0) ? MVT::i16 :MVT::i8));
Reg = getX86SubSuperRegister(Reg, VT);
}
O << RI.get(Reg).Name;
return;
case MachineOperand::MO_Immediate:
- O << (int)MO.getImmedValue();
+ O << MO.getImmedValue();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMachineBasicBlock());
case MachineOperand::MO_ConstantPoolIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (!isMemOp) O << "OFFSET ";
- O << "[" << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
- << MO.getConstantPoolIndex();
+ O << "[" << TAI->getPrivateGlobalPrefix() << "CPI"
+ << getFunctionNumber() << "_" << MO.getConstantPoolIndex();
int Offset = MO.getOffset();
if (Offset > 0)
O << " + " << Offset;
case MachineOperand::MO_GlobalAddress: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
+ GlobalValue *GV = MO.getGlobal();
+ std::string Name = Mang->getValueName(GV);
+
+ X86SharedAsmPrinter::decorateName(Name, GV);
+
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 << Name;
int Offset = MO.getOffset();
if (Offset > 0)
O << " + " << Offset;
case MachineOperand::MO_ExternalSymbol: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
if (!isCallOp) O << "OFFSET ";
- O << GlobalPrefix << MO.getSymbolName();
+ O << TAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
default:
}
}
-void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
+void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
+ const char *Modifier) {
assert(isMem(MI, Op) && "Invalid memory reference!");
const MachineOperand &BaseReg = MI->getOperand(Op);
O << "[";
bool NeedPlus = false;
if (BaseReg.getReg()) {
- printOp(BaseReg, "mem");
+ printOp(BaseReg, Modifier);
NeedPlus = true;
}
if (NeedPlus) O << " + ";
if (ScaleVal != 1)
O << ScaleVal << "*";
- printOp(IndexReg);
+ printOp(IndexReg, Modifier);
NeedPlus = true;
}
// See if a truncate instruction can be turned into a nop.
switch (MI->getOpcode()) {
default: break;
- case X86::TRUNC_GR32_GR16:
- case X86::TRUNC_GR32_GR8:
- case X86::TRUNC_GR16_GR8: {
+ case X86::TRUNC_64to32:
+ case X86::TRUNC_64to16:
+ case X86::TRUNC_32to16:
+ case X86::TRUNC_32to8:
+ case X86::TRUNC_16to8:
+ case X86::TRUNC_32_to8:
+ case X86::TRUNC_16_to8: {
const MachineOperand &MO0 = MI->getOperand(0);
const MachineOperand &MO1 = MI->getOperand(1);
unsigned Reg0 = MO0.getReg();
unsigned Reg1 = MO1.getReg();
- if (MI->getOpcode() == X86::TRUNC_GR32_GR16)
+ unsigned Opc = MI->getOpcode();
+ if (Opc == X86::TRUNC_64to32)
+ Reg1 = getX86SubSuperRegister(Reg1, MVT::i32);
+ else if (Opc == X86::TRUNC_32to16 || Opc == X86::TRUNC_64to16)
Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
else
Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
- O << CommentString << " TRUNCATE ";
+ O << TAI->getCommentString() << " TRUNCATE ";
if (Reg0 != Reg1)
O << "\n\t";
break;
}
+ case X86::PsMOVZX64rr32:
+ O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t";
+ break;
}
// Call the autogenerated instruction printer routines.
}
bool X86IntelAsmPrinter::doInitialization(Module &M) {
- GlobalPrefix = "_";
- CommentString = ";";
-
X86SharedAsmPrinter::doInitialization(M);
-
- PrivateGlobalPrefix = "$";
- AlignDirective = "\talign\t";
- ZeroDirective = "\tdb\t";
- ZeroDirectiveSuffix = " dup(0)";
- AsciiDirective = "\tdb\t";
- AscizDirective = 0;
- Data8bitsDirective = "\tdb\t";
- Data16bitsDirective = "\tdw\t";
- Data32bitsDirective = "\tdd\t";
- Data64bitsDirective = "\tdq\t";
- HasDotTypeDotSizeDirective = false;
- Mang->markCharUnacceptable('.');
- DefaultTextSection = "_text";
- DefaultDataSection = "_data";
- SwitchToSectionDirective = "";
- TextSectionStartSuffix = "\tsegment 'CODE'";
- DataSectionStartSuffix = "\tsegment 'DATA'";
- SectionEndDirectiveSuffix = "\tends\n";
+ Mang->markCharUnacceptable('.');
O << "\t.686\n\t.model flat\n\n";
// Emit declarations for external functions.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (I->isExternal())
- O << "\textern " << Mang->getValueName(I) << ":near\n";
-
+ if (I->isExternal()) {
+ std::string Name = Mang->getValueName(I);
+ X86SharedAsmPrinter::decorateName(Name, I);
+
+ O << "\textern " ;
+ if (I->hasDLLImportLinkage()) {
+ O << "__imp_";
+ }
+ O << Name << ":near\n";
+ }
+
// Emit declarations for external globals. Note that VC++ always declares
// external globals to have type byte, and if that's good enough for VC++...
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
- if (I->isExternal())
- O << "\textern " << Mang->getValueName(I) << ":byte\n";
+ if (I->isExternal()) {
+ std::string Name = Mang->getValueName(I);
+
+ O << "\textern " ;
+ if (I->hasDLLImportLinkage()) {
+ O << "__imp_";
+ }
+ O << Name << ":byte\n";
+ }
}
return false;
// 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
case GlobalValue::InternalLinkage:
- SwitchToDataSection(DefaultDataSection, I);
+ SwitchToDataSection(TAI->getDataSection(), I);
break;
default:
assert(0 && "Unknown linkage type!");
if (!bCustomSegment)
EmitAlignment(Align, I);
- O << name << ":\t\t\t\t" << CommentString << " " << I->getName() << '\n';
+ O << name << ":\t\t\t\t" << TAI->getCommentString()
+ << " " << I->getName() << '\n';
EmitGlobalConstant(C);
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);