X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FXCore%2FXCoreAsmPrinter.cpp;h=8f06dd32662f2dbcf0e8d6ec1ad63e27c47667fd;hb=09aa3f0ef35d9241c92439d74b8d5e9a81d814c2;hp=57530c39428f24d69ca8013ae992c9b5f1eaa183;hpb=ceb4d1aecb9deffe59b3dcdc9a783ffde8477be9;p=oota-llvm.git diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 57530c39428..8f06dd32662 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -16,36 +16,32 @@ #include "XCore.h" #include "XCoreInstrInfo.h" #include "XCoreSubtarget.h" +#include "XCoreMCAsmInfo.h" #include "XCoreTargetMachine.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.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/MachineInstr.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" -#include "llvm/Support/Mangler.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.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, @@ -53,409 +49,232 @@ static cl::opt MaxThreads("xcore-max-threads", cl::Optional, cl::init(8)); namespace { - struct VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter { - XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM, - const TargetAsmInfo *T) - : AsmPrinter(O, TM, T), DW(0), - Subtarget(*TM.getSubtargetImpl()) { } - - DwarfWriter *DW; + class XCoreAsmPrinter : public AsmPrinter { const XCoreSubtarget &Subtarget; + public: + explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget()){} virtual const char *getPassName() const { return "XCore Assembly Printer"; } - void printMemOperand(const MachineInstr *MI, int opNum); - void printOperand(const MachineInstr *MI, int opNum); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + 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); - - 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); + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); - void emitFunctionStart(MachineFunction &MF); - void emitFunctionEnd(MachineFunction &MF); + void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV); + virtual void EmitGlobalVariable(const GlobalVariable *GV); - 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(); - AU.addRequired(); - } + void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. + static const char *getRegisterName(unsigned RegNo); + + void EmitFunctionEntryLabel(); + void EmitInstruction(const MachineInstr *MI); + void EmitFunctionBodyEnd(); }; } // 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()); -} - -// 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:: -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) -{ +void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, 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"; + cast(GV->getType())->getElementType())) { + OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); + // FIXME: MCStreamerize. + OutStreamer.EmitRawText(StringRef(".globound")); + OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName())); + OutStreamer.EmitRawText(".globound," + Twine(ATy->getNumElements())); if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { // TODO Use COMDAT groups for LinkOnceLinkage - O << TAI->getWeakDefDirective() << name << ".globound" << "\n"; + OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+ + ".globound"); } } } -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"; - - 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!"); - } - - EmitAlignment(Align, GV, 2); - - unsigned Size = TD->getTypePaddedSize(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); - } -} +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; -/// 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(); + const TargetData *TD = TM.getTargetData(); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); - SwitchToSection(TAI->SectionForGlobal(F)); - // Mark the start of the function - O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; + MCSymbol *GVSym = Mang->getSymbol(GV); + Constant *C = GV->getInitializer(); + unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); + + // Mark the start of the global + OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," + + 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: + emitArrayBound(GVSym, GV); + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - 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"; + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); + // FALL THROUGH + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: break; + case GlobalValue::DLLImportLinkage: + llvm_unreachable("DLLImport linkage is not supported by this target!"); + case GlobalValue::DLLExportLinkage: + llvm_unreachable("DLLExport linkage is not supported by this target!"); + default: + llvm_unreachable("Unknown linkage type!"); } - // (1 << 1) byte aligned - EmitAlignment(1, F, 1); - if (TAI->hasDotTypeDotSizeDirective()) { - O << "\t.type " << CurrentFnName << ",@function\n"; - } - O << CurrentFnName << ":\n"; -} - -/// 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"; -} - -/// 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); + EmitAlignment(Align > 2 ? Align : 2, GV); - // 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'; + unsigned Size = TD->getTypeAllocSize(C->getType()); + if (GV->isThreadLocal()) { + Size *= MaxThreads; + } + if (MAI->hasDotTypeDotSizeDirective()) { + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); + OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + + Twine(Size)); } + OutStreamer.EmitLabel(GVSym); + + EmitGlobalConstant(C); + if (GV->isThreadLocal()) { + for (unsigned i = 1; i < MaxThreads; ++i) + 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, 0); + + // Mark the end of the global + OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data"); +} +/// 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); + OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) + + ".function"); +} - // We didn't modify anything. - return false; +void XCoreAsmPrinter::EmitFunctionEntryLabel() { + // Mark the start of the function + OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) + + ".function," + CurrentFnSym->getName()); + OutStreamer.EmitLabel(CurrentFnSym); } -void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) -{ - printOperand(MI, opNum); +void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + printOperand(MI, opNum, O); - if (MI->getOperand(opNum+1).isImm() - && MI->getOperand(opNum+1).getImm() == 0) + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) return; O << "+"; - printOperand(MI, opNum+1); + printOperand(MI, opNum+1, O); +} + +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 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 << 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()); + O << *Mang->getSymbol(MO.getGlobal()); break; case MachineOperand::MO_ExternalSymbol: O << MO.getSymbolName(); break; case MachineOperand::MO_ConstantPoolIndex: - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' << MO.getIndex(); break; case MachineOperand::MO_JumpTableIndex: - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' << MO.getIndex(); break; + 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); + unsigned AsmVariant,const char *ExtraCode, + raw_ostream &O) { + printOperand(MI, OpNo, O); return false; } -void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; +void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); // 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; - } - if (printInstruction(MI)) { - return; - } - assert(0 && "Unhandled instruction in asm writer!"); + if (MI->getOpcode() == XCore::ADD_2rus && !MI->getOperand(2).getImm()) + O << "\tmov " << getRegisterName(MI->getOperand(0).getReg()) << ", " + << getRegisterName(MI->getOperand(1).getReg()); + else + printInstruction(MI, O); + OutStreamer.EmitRawText(O.str()); } -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; - } - } - } - - // Emit initial debug information. - DW = getAnalysisToUpdate(); - assert(DW && "Dwarf Writer is not available"); - DW->BeginModule(&M, getAnalysisToUpdate(), - O, this, TAI); - return Result; -} - -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); }