X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FXCore%2FXCoreAsmPrinter.cpp;h=23e24f2afd5a4cf214aa0ce21396230e736cc974;hp=519b38bdfa98d1e4921bb254fb166c3df8d28670;hb=19696daa2159e059b9a15cda222e97d2b91b279d;hpb=b25baef26f03b9909b65dd5f762b38f93000445d diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 519b38bdfa9..23e24f2afd5 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -12,448 +12,293 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "XCore.h" +#include "InstPrinter/XCoreInstPrinter.h" #include "XCoreInstrInfo.h" +#include "XCoreMCInstLower.h" #include "XCoreSubtarget.h" #include "XCoreTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" +#include "XCoreTargetStreamer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DwarfWriter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/Mangler.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include #include using namespace llvm; -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - -static cl::opt FileDirective("xcore-file-directive", cl::Optional, - cl::desc("Output a file directive into the assembly file"), - cl::Hidden, - cl::value_desc("filename"), - cl::init("")); - -static cl::opt MaxThreads("xcore-max-threads", cl::Optional, - cl::desc("Maximum number of threads (for emulation thread-local storage)"), - cl::Hidden, - cl::value_desc("number"), - cl::init(8)); +#define DEBUG_TYPE "asm-printer" namespace { - struct VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter { - XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM, - const TargetAsmInfo *T) - : AsmPrinter(O, TM, T), DW(O, this, T), - Subtarget(*TM.getSubtargetImpl()) { } + class XCoreAsmPrinter : public AsmPrinter { + XCoreMCInstLower MCInstLowering; + XCoreTargetStreamer &getTargetStreamer(); - DwarfWriter DW; - const XCoreSubtarget &Subtarget; + public: + explicit XCoreAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "XCore Assembly Printer"; } - void printMemOperand(const MachineInstr *MI, int opNum); - void printOperand(const MachineInstr *MI, int opNum); - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode); - - void emitFileDirective(const std::string &filename); - void emitGlobalDirective(const std::string &name); - void emitExternDirective(const std::string &name); - - void emitArrayBound(const std::string &name, const GlobalVariable *GV); - void emitGlobal(const GlobalVariable *GV); - - void emitFunctionStart(MachineFunction &MF); - void emitFunctionEnd(MachineFunction &MF); - - bool printInstruction(const MachineInstr *MI); // autogenerated. - void printMachineInstruction(const MachineInstr *MI); - bool runOnMachineFunction(MachineFunction &F); - bool doInitialization(Module &M); - bool doFinalization(Module &M); - - void getAnalysisUsage(AnalysisUsage &AU) const { - AsmPrinter::getAnalysisUsage(AU); - AU.setPreservesAll(); - AU.addRequired(); + void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, + const std::string &directive = ".jmptable"); + void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) { + printInlineJT(MI, opNum, O, ".jmptable32"); } + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) override; + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) override; + + void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV); + void EmitGlobalVariable(const GlobalVariable *GV) override; + + void EmitFunctionEntryLabel() override; + void EmitInstruction(const MachineInstr *MI) override; + void EmitFunctionBodyStart() override; + void EmitFunctionBodyEnd() override; }; } // end of anonymous namespace -#include "XCoreGenAsmWriter.inc" - -/// createXCoreCodePrinterPass - Returns a pass that prints the XCore -/// assembly code for a MachineFunction to the given output stream, -/// using the given target machine description. This should work -/// regardless of whether the function is in SSA form. -/// -FunctionPass *llvm::createXCoreCodePrinterPass(raw_ostream &o, - XCoreTargetMachine &tm) { - return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo()); +XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() { + return static_cast(*OutStreamer->getTargetStreamer()); } -// PrintEscapedString - Print each character of the specified string, escaping -// it if it is not printable or if it is an escape char. -static void PrintEscapedString(const std::string &Str, raw_ostream &Out) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - unsigned char C = Str[i]; - if (isprint(C) && C != '"' && C != '\\') { - Out << C; - } else { - Out << '\\' - << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')) - << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); +void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { + assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) && + "Unexpected linkage"); + if (ArrayType *ATy = dyn_cast( + cast(GV->getType())->getElementType())) { + + MCSymbol *SymGlob = OutContext.getOrCreateSymbol( + Twine(Sym->getName() + StringRef(".globound"))); + OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Global); + OutStreamer->EmitAssignment(SymGlob, + MCConstantExpr::Create(ATy->getNumElements(), + OutContext)); + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || + GV->hasCommonLinkage()) { + OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Weak); } } } -void XCoreAsmPrinter:: -emitFileDirective(const std::string &name) -{ - O << "\t.file\t\""; - PrintEscapedString(name, O); - O << "\"\n"; -} - -void XCoreAsmPrinter:: -emitGlobalDirective(const std::string &name) -{ - O << TAI->getGlobalDirective() << name; - O << "\n"; -} - -void XCoreAsmPrinter:: -emitExternDirective(const std::string &name) -{ - O << "\t.extern\t" << name; - O << '\n'; -} - -void XCoreAsmPrinter:: -emitArrayBound(const std::string &name, const GlobalVariable *GV) -{ - assert((GV->hasExternalLinkage() || - GV->hasWeakLinkage()) || - GV->hasLinkOnceLinkage() && "Unexpected linkage"); - if (const ArrayType *ATy = dyn_cast( - cast(GV->getType())->getElementType())) - { - O << TAI->getGlobalDirective() << name << ".globound" << "\n"; - O << TAI->getSetDirective() << name << ".globound" << "," - << ATy->getNumElements() << "\n"; - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { - // TODO Use COMDAT groups for LinkOnceLinkage - O << TAI->getWeakDefDirective() << name << ".globound" << "\n"; - } - } -} - -void XCoreAsmPrinter:: -emitGlobal(const GlobalVariable *GV) -{ - const TargetData *TD = TM.getTargetData(); - - if (GV->hasInitializer()) { - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GV)) - return; - - SwitchToSection(TAI->SectionForGlobal(GV)); - - std::string name = Mang->getValueName(GV); - Constant *C = GV->getInitializer(); - unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); - - // Mark the start of the global - O << "\t.cc_top " << name << ".data," << name << "\n"; +void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { + // Check to see if this is a special global used by LLVM, if so, emit it. + if (!GV->hasInitializer() || + EmitSpecialLLVMGlobal(GV)) + return; - switch (GV->getLinkage()) { - case GlobalValue::AppendingLinkage: - cerr << "AppendingLinkage is not supported by this target!\n"; - abort(); - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: - case GlobalValue::ExternalLinkage: - emitArrayBound(name, GV); - emitGlobalDirective(name); - // TODO Use COMDAT groups for LinkOnceLinkage - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { - O << TAI->getWeakDefDirective() << name << "\n"; - } - // FALL THROUGH - case GlobalValue::InternalLinkage: - break; - case GlobalValue::GhostLinkage: - cerr << "Should not have any unmaterialized functions!\n"; - abort(); - case GlobalValue::DLLImportLinkage: - cerr << "DLLImport linkage is not supported by this target!\n"; - abort(); - case GlobalValue::DLLExportLinkage: - cerr << "DLLExport linkage is not supported by this target!\n"; - abort(); - default: - assert(0 && "Unknown linkage type!"); - } + const DataLayout *TD = TM.getDataLayout(); + OutStreamer->SwitchSection( + getObjFileLowering().SectionForGlobal(GV, *Mang, TM)); - EmitAlignment(Align, GV, 2); - - unsigned Size = TD->getABITypeSize(C->getType()); - if (GV->isThreadLocal()) { - Size *= MaxThreads; - } - if (TAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << name << ",@object\n"; - O << "\t.size " << name << "," << Size << "\n"; - } - O << name << ":\n"; - - EmitGlobalConstant(C); - if (GV->isThreadLocal()) { - for (unsigned i = 1; i < MaxThreads; ++i) { - EmitGlobalConstant(C); - } - } - if (Size < 4) { - // The ABI requires that unsigned scalar types smaller than 32 bits - // are are padded to 32 bits. - EmitZeros(4 - Size); - } - - // Mark the end of the global - O << "\t.cc_bottom " << name << ".data\n"; - } else { - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); + MCSymbol *GVSym = getSymbol(GV); + const Constant *C = GV->getInitializer(); + unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); + + // Mark the start of the global + getTargetStreamer().emitCCTopData(GVSym->getName()); + + switch (GV->getLinkage()) { + case GlobalValue::AppendingLinkage: + report_fatal_error("AppendingLinkage is not supported by this target!"); + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::ExternalLinkage: + case GlobalValue::CommonLinkage: + emitArrayBound(GVSym, GV); + OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || + GV->hasCommonLinkage()) + OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak); + // FALL THROUGH + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); } -} - -/// Emit the directives on the start of functions -void XCoreAsmPrinter:: -emitFunctionStart(MachineFunction &MF) -{ - // Print out the label for the function. - const Function *F = MF.getFunction(); - SwitchToSection(TAI->SectionForGlobal(F)); + EmitAlignment(Align > 2 ? Align : 2, GV); - // Mark the start of the function - O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; - - switch (F->getLinkage()) { - default: assert(0 && "Unknown linkage type!"); - case Function::InternalLinkage: // Symbols default to internal. - break; - case Function::ExternalLinkage: - emitGlobalDirective(CurrentFnName); - break; - case Function::LinkOnceLinkage: - case Function::WeakLinkage: - // TODO Use COMDAT groups for LinkOnceLinkage - O << TAI->getGlobalDirective() << CurrentFnName << "\n"; - O << TAI->getWeakDefDirective() << CurrentFnName << "\n"; - break; + if (GV->isThreadLocal()) { + report_fatal_error("TLS is not supported by this target!"); } - // (1 << 1) byte aligned - EmitAlignment(1, F, 1); - if (TAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << CurrentFnName << ",@function\n"; + unsigned Size = TD->getTypeAllocSize(C->getType()); + if (MAI->hasDotTypeDotSizeDirective()) { + OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); + OutStreamer->EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); } - O << CurrentFnName << ":\n"; + OutStreamer->EmitLabel(GVSym); + + EmitGlobalConstant(C); + // The ABI requires that unsigned scalar types smaller than 32 bits + // are padded to 32 bits. + if (Size < 4) + OutStreamer->EmitZeros(4 - Size); + + // Mark the end of the global + getTargetStreamer().emitCCBottomData(GVSym->getName()); } -/// Emit the directives on the end of functions -void XCoreAsmPrinter:: -emitFunctionEnd(MachineFunction &MF) -{ - // Mark the end of the function - O << "\t.cc_bottom " << CurrentFnName << ".function\n"; +void XCoreAsmPrinter::EmitFunctionBodyStart() { + MCInstLowering.Initialize(Mang, &MF->getContext()); } -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) -{ - SetupMachineFunction(MF); - - // Print out constants referenced by the function - EmitConstantPool(MF.getConstantPool()); - - // Print out jump tables referenced by the function - EmitJumpTableInfo(MF.getJumpTableInfo(), MF); - - // What's my mangled name? - CurrentFnName = Mang->getValueName(MF.getFunction()); - - // Emit the function start directives - emitFunctionStart(MF); - - // Emit pre-function debug information. - DW.BeginFunction(&MF); - - // Print out code for the function. - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - - // Print a label for the basic block. - if (I != MF.begin()) { - printBasicBlockLabel(I, true , true); - O << '\n'; - } - - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - O << "\t"; - printMachineInstruction(II); - } - - // Each Basic Block is separated by a newline - O << '\n'; - } - +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void XCoreAsmPrinter::EmitFunctionBodyEnd() { // Emit function end directives - emitFunctionEnd(MF); - - // Emit post-function debug information. - DW.EndFunction(&MF); + getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName()); +} - // We didn't modify anything. - return false; +void XCoreAsmPrinter::EmitFunctionEntryLabel() { + // Mark the start of the function + getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName()); + OutStreamer->EmitLabel(CurrentFnSym); } -void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) -{ - printOperand(MI, opNum); - - if (MI->getOperand(opNum+1).isImm() - && MI->getOperand(opNum+1).getImm() == 0) - return; - - O << "+"; - printOperand(MI, opNum+1); +void XCoreAsmPrinter:: +printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, + const std::string &directive) { + unsigned JTI = MI->getOperand(opNum).getIndex(); + const MachineFunction *MF = MI->getParent()->getParent(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + O << "\t" << directive << " "; + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + if (i > 0) + O << ","; + O << *MBB->getSymbol(); + } } -void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { +void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { case MachineOperand::MO_Register: - if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) - O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; - else - assert(0 && "not implemented"); + O << XCoreInstPrinter::getRegisterName(MO.getReg()); break; case MachineOperand::MO_Immediate: O << MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMBB()); + O << *MO.getMBB()->getSymbol(); break; case MachineOperand::MO_GlobalAddress: - O << Mang->getValueName(MO.getGlobal()); - if (MO.getGlobal()->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(MO.getGlobal()); - break; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); + O << *getSymbol(MO.getGlobal()); break; case MachineOperand::MO_ConstantPoolIndex: - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); break; - case MachineOperand::MO_JumpTableIndex: - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); + case MachineOperand::MO_BlockAddress: + O << *GetBlockAddressSymbol(MO.getBlockAddress()); break; default: - assert(0 && "not implemented"); + llvm_unreachable("not implemented"); } } /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - printOperand(MI, OpNo); - return false; -} + unsigned AsmVariant,const char *ExtraCode, + raw_ostream &O) { + // Print the operand if there is no operand modifier. + if (!ExtraCode || !ExtraCode[0]) { + printOperand(MI, OpNo, O); + return false; + } -void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; + // Otherwise fallback on the default implementation. + return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); +} - // Check for mov mnemonic - unsigned src, dst; - if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst)) { - O << "\tmov "; - O << TM.getRegisterInfo()->get(dst).AsmName; - O << ", "; - O << TM.getRegisterInfo()->get(src).AsmName; - O << "\n"; - return; +bool XCoreAsmPrinter:: +PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) { + return true; // Unknown modifier. } - if (printInstruction(MI)) { - return; - } - assert(0 && "Unhandled instruction in asm writer!"); + printOperand(MI, OpNum, O); + O << '['; + printOperand(MI, OpNum + 1, O); + O << ']'; + return false; } -bool XCoreAsmPrinter::doInitialization(Module &M) { - bool Result = AsmPrinter::doInitialization(M); - - if (!FileDirective.empty()) { - emitFileDirective(FileDirective); - } - - // Print out type strings for external functions here - for (Module::const_iterator I = M.begin(), E = M.end(); - I != E; ++I) { - if (I->isDeclaration() && !I->isIntrinsic()) { - switch (I->getLinkage()) { - default: - assert(0 && "Unexpected linkage"); - case Function::ExternalWeakLinkage: - ExtWeakSymbols.insert(I); - // fallthrough - case Function::ExternalLinkage: - break; - } +void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); + + switch (MI->getOpcode()) { + case XCore::DBG_VALUE: + llvm_unreachable("Should be handled target independently"); + case XCore::ADD_2rus: + if (MI->getOperand(2).getImm() == 0) { + O << "\tmov " + << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", " + << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()); + OutStreamer->EmitRawText(O.str()); + return; } + break; + case XCore::BR_JT: + case XCore::BR_JT32: + O << "\tbru " + << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n'; + if (MI->getOpcode() == XCore::BR_JT) + printInlineJT(MI, 0, O); + else + printInlineJT32(MI, 0, O); + O << '\n'; + OutStreamer->EmitRawText(O.str()); + return; } - // Emit initial debug information. - DW.BeginModule(&M); + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); - DW.SetModuleInfo(getAnalysisToUpdate()); - return Result; + EmitToStreamer(*OutStreamer, TmpInst); } -bool XCoreAsmPrinter::doFinalization(Module &M) { - - // Print out module-level global variables. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { - emitGlobal(I); - } - - // Emit final debug information. - DW.EndModule(); - - return AsmPrinter::doFinalization(M); +// Force static initialization. +extern "C" void LLVMInitializeXCoreAsmPrinter() { + RegisterAsmPrinter X(TheXCoreTarget); }