X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter.cpp;h=05761d164769b7ac8ea9f2feddb64fd07382f4fa;hb=ab4022f196059745c0ca0780b71a80fa67e896be;hp=ca9b50bb81229ebe917bcb245d602ac206dbded9;hpb=4a6bd33da0e30c26568baf3ad6c94d1f497e5ea7;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp index ca9b50bb812..05761d16476 100644 --- a/lib/CodeGen/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter.cpp @@ -20,49 +20,21 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include #include using namespace llvm; -AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm) -: FunctionNumber(0), O(o), TM(tm), - CommentString("#"), - GlobalPrefix(""), - PrivateGlobalPrefix("."), - GlobalVarAddrPrefix(""), - GlobalVarAddrSuffix(""), - FunctionAddrPrefix(""), - FunctionAddrSuffix(""), - InlineAsmStart("#APP"), - InlineAsmEnd("#NO_APP"), - ZeroDirective("\t.zero\t"), - ZeroDirectiveSuffix(0), - AsciiDirective("\t.ascii\t"), - AscizDirective("\t.asciz\t"), - Data8bitsDirective("\t.byte\t"), - Data16bitsDirective("\t.short\t"), - Data32bitsDirective("\t.long\t"), - Data64bitsDirective("\t.quad\t"), - AlignDirective("\t.align\t"), - AlignmentIsInBytes(true), - SwitchToSectionDirective("\t.section\t"), - TextSectionStartSuffix(""), - DataSectionStartSuffix(""), - SectionEndDirectiveSuffix(0), - ConstantPoolSection("\t.section .rodata\n"), - JumpTableDataSection("\t.section .rodata\n"), - JumpTableTextSection("\t.text\n"), - StaticCtorsSection("\t.section .ctors,\"aw\",@progbits"), - StaticDtorsSection("\t.section .dtors,\"aw\",@progbits"), - FourByteConstantSection(0), - EightByteConstantSection(0), - SixteenByteConstantSection(0), - LCOMMDirective(0), - COMMDirective("\t.comm\t"), - COMMDirectiveTakesAlignment(true), - HasDotTypeDotSizeDirective(true) { +AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm, + const TargetAsmInfo *T) +: FunctionNumber(0), O(o), TM(tm), TAI(T) +{} + +std::string AsmPrinter::getSectionForFunction(const Function &F) const { + return TAI->getTextSection(); } @@ -73,7 +45,7 @@ void AsmPrinter::SwitchToTextSection(const char *NewSection, const GlobalValue *GV) { std::string NS; if (GV && GV->hasSection()) - NS = SwitchToSectionDirective + GV->getSection(); + NS = TAI->getSwitchToSectionDirective() + GV->getSection(); else NS = NewSection; @@ -81,13 +53,13 @@ void AsmPrinter::SwitchToTextSection(const char *NewSection, if (CurrentSection == NS) return; // Close the current section, if applicable. - if (SectionEndDirectiveSuffix && !CurrentSection.empty()) - O << CurrentSection << SectionEndDirectiveSuffix << "\n"; + if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) + O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << "\n"; CurrentSection = NS; if (!CurrentSection.empty()) - O << CurrentSection << TextSectionStartSuffix << '\n'; + O << CurrentSection << TAI->getTextSectionStartSuffix() << '\n'; } /// SwitchToDataSection - Switch to the specified data section of the executable @@ -97,7 +69,7 @@ void AsmPrinter::SwitchToDataSection(const char *NewSection, const GlobalValue *GV) { std::string NS; if (GV && GV->hasSection()) - NS = SwitchToSectionDirective + GV->getSection(); + NS = TAI->getSwitchToSectionDirective() + GV->getSection(); else NS = NewSection; @@ -105,25 +77,26 @@ void AsmPrinter::SwitchToDataSection(const char *NewSection, if (CurrentSection == NS) return; // Close the current section, if applicable. - if (SectionEndDirectiveSuffix && !CurrentSection.empty()) - O << CurrentSection << SectionEndDirectiveSuffix << "\n"; + if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) + O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << "\n"; CurrentSection = NS; if (!CurrentSection.empty()) - O << CurrentSection << DataSectionStartSuffix << '\n'; + O << CurrentSection << TAI->getDataSectionStartSuffix() << '\n'; } bool AsmPrinter::doInitialization(Module &M) { - Mang = new Mangler(M, GlobalPrefix); + Mang = new Mangler(M, TAI->getGlobalPrefix()); if (!M.getModuleInlineAsm().empty()) - O << CommentString << " Start of file scope inline assembly\n" + O << TAI->getCommentString() << " Start of file scope inline assembly\n" << M.getModuleInlineAsm() - << "\n" << CommentString << " End of file scope inline assembly\n"; + << "\n" << TAI->getCommentString() + << " End of file scope inline assembly\n"; - SwitchToDataSection("", 0); // Reset back to no section. + SwitchToDataSection(""); // Reset back to no section. if (MachineDebugInfo *DebugInfo = getAnalysisToUpdate()) { DebugInfo->AnalyzeModule(M); @@ -158,17 +131,17 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { std::vector > EightByteCPs; std::vector > SixteenByteCPs; std::vector > OtherCPs; + std::vector > TargetCPs; for (unsigned i = 0, e = CP.size(); i != e; ++i) { MachineConstantPoolEntry CPE = CP[i]; - const Constant *CV = CPE.Val; - const Type *Ty = CV->getType(); - if (FourByteConstantSection && + const Type *Ty = CPE.getType(); + if (TAI->getFourByteConstantSection() && TM.getTargetData()->getTypeSize(Ty) == 4) FourByteCPs.push_back(std::make_pair(CPE, i)); - else if (EightByteConstantSection && + else if (TAI->getEightByteConstantSection() && TM.getTargetData()->getTypeSize(Ty) == 8) EightByteCPs.push_back(std::make_pair(CPE, i)); - else if (SixteenByteConstantSection && + else if (TAI->getSixteenByteConstantSection() && TM.getTargetData()->getTypeSize(Ty) == 16) SixteenByteCPs.push_back(std::make_pair(CPE, i)); else @@ -176,29 +149,34 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { } unsigned Alignment = MCP->getConstantPoolAlignment(); - EmitConstantPool(Alignment, FourByteConstantSection, FourByteCPs); - EmitConstantPool(Alignment, EightByteConstantSection, EightByteCPs); - EmitConstantPool(Alignment, SixteenByteConstantSection, SixteenByteCPs); - EmitConstantPool(Alignment, ConstantPoolSection, OtherCPs); + EmitConstantPool(Alignment, TAI->getFourByteConstantSection(), FourByteCPs); + EmitConstantPool(Alignment, TAI->getEightByteConstantSection(), EightByteCPs); + EmitConstantPool(Alignment, TAI->getSixteenByteConstantSection(), + SixteenByteCPs); + EmitConstantPool(Alignment, TAI->getConstantPoolSection(), OtherCPs); } void AsmPrinter::EmitConstantPool(unsigned Alignment, const char *Section, std::vector > &CP) { if (CP.empty()) return; - SwitchToDataSection(Section, 0); + SwitchToDataSection(Section); EmitAlignment(Alignment); for (unsigned i = 0, e = CP.size(); i != e; ++i) { - O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << '_' - << CP[i].second << ":\t\t\t\t\t" << CommentString << " "; - WriteTypeSymbolic(O, CP[i].first.Val->getType(), 0) << '\n'; - EmitGlobalConstant(CP[i].first.Val); + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << CP[i].second << ":\t\t\t\t\t" << TAI->getCommentString() << " "; + WriteTypeSymbolic(O, CP[i].first.getType(), 0) << '\n'; + if (CP[i].first.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(CP[i].first.Val.MachineCPVal); + else + EmitGlobalConstant(CP[i].first.Val.ConstVal); if (i != e-1) { + const Type *Ty = CP[i].first.getType(); unsigned EntSize = - TM.getTargetData()->getTypeSize(CP[i].first.Val->getType()); - unsigned ValEnd = CP[i].first.Offset + EntSize; + TM.getTargetData()->getTypeSize(Ty); + unsigned ValEnd = CP[i].first.getOffset() + EntSize; // Emit inter-object padding for alignment. - EmitZeros(CP[i+1].first.Offset-ValEnd); + EmitZeros(CP[i+1].first.getOffset()-ValEnd); } } } @@ -206,7 +184,8 @@ void AsmPrinter::EmitConstantPool(unsigned Alignment, const char *Section, /// EmitJumpTableInfo - Print assembly representations of the jump tables used /// by the current function to the current output stream. /// -void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI) { +void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, + MachineFunction &MF) { const std::vector &JT = MJTI->getJumpTables(); if (JT.empty()) return; const TargetData *TD = TM.getTargetData(); @@ -214,29 +193,68 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI) { // JTEntryDirective is a string to print sizeof(ptr) for non-PIC jump tables, // and 32 bits for PIC since PIC jump table entries are differences, not // pointers to blocks. - const char *JTEntryDirective = Data32bitsDirective; + // Use the architecture specific relocation directive, if it is set + const char *JTEntryDirective = TAI->getJumpTableDirective(); + if (!JTEntryDirective) + JTEntryDirective = TAI->getData32bitsDirective(); // Pick the directive to use to print the jump table entries, and switch to // the appropriate section. if (TM.getRelocationModel() == Reloc::PIC_) { - SwitchToTextSection(JumpTableTextSection, 0); + TargetLowering *LoweringInfo = TM.getTargetLowering(); + if (LoweringInfo && LoweringInfo->usesGlobalOffsetTable()) { + SwitchToDataSection(TAI->getJumpTableDataSection()); + if (TD->getPointerSize() == 8 && !JTEntryDirective) + JTEntryDirective = TAI->getData64bitsDirective(); + } else { + // In PIC mode, we need to emit the jump table to the same section as the + // function body itself, otherwise the label differences won't make sense. + const Function *F = MF.getFunction(); + SwitchToTextSection(getSectionForFunction(*F).c_str(), F); + } } else { - SwitchToDataSection(JumpTableDataSection, 0); + SwitchToDataSection(TAI->getJumpTableDataSection()); if (TD->getPointerSize() == 8) - JTEntryDirective = Data64bitsDirective; + JTEntryDirective = TAI->getData64bitsDirective(); } EmitAlignment(Log2_32(TD->getPointerAlignment())); for (unsigned i = 0, e = JT.size(); i != e; ++i) { - O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << '_' << i - << ":\n"; const std::vector &JTBBs = JT[i].MBBs; + + // If this jump table was deleted, ignore it. + if (JTBBs.empty()) continue; + + // For PIC codegen, if possible we want to use the SetDirective to reduce + // the number of relocations the assembler will generate for the jump table. + // Set directives are all printed before the jump table itself. + std::set EmittedSets; + if (TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_) + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) + if (EmittedSets.insert(JTBBs[ii]).second) + printSetLabel(i, JTBBs[ii]); + + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << i << ":\n"; + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { O << JTEntryDirective << ' '; - printBasicBlockLabel(JTBBs[ii], false, false); - if (TM.getRelocationModel() == Reloc::PIC_) { - O << '-' << PrivateGlobalPrefix << "JTI" << getFunctionNumber() - << '_' << i; + // If we have emitted set directives for the jump table entries, print + // them rather than the entries themselves. If we're emitting PIC, then + // emit the table entries as differences between two text section labels. + // If we're emitting non-PIC code, then emit the entries as direct + // references to the target basic blocks. + if (!EmittedSets.empty()) { + O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() + << '_' << i << "_set_" << JTBBs[ii]->getNumber(); + } else if (TM.getRelocationModel() == Reloc::PIC_) { + printBasicBlockLabel(JTBBs[ii], false, false); + //If the arch uses custom Jump Table directives, don't calc relative to JT + if (!TAI->getJumpTableDirective()) + O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" + << getFunctionNumber() << '_' << i; + } else { + printBasicBlockLabel(JTBBs[ii], false, false); } O << '\n'; } @@ -254,18 +272,21 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { assert(GV->hasInitializer() && "Not a special LLVM global!"); - if (GV->getName() == "llvm.used") - return true; // No need to emit this at all. + if (GV->getName() == "llvm.used") { + if (TAI->getUsedDirective() != 0) // No need to emit this at all. + EmitLLVMUsedList(GV->getInitializer()); + return true; + } if (GV->getName() == "llvm.global_ctors" && GV->use_empty()) { - SwitchToDataSection(StaticCtorsSection, 0); + SwitchToDataSection(TAI->getStaticCtorsSection()); EmitAlignment(2, 0); EmitXXStructorList(GV->getInitializer()); return true; } if (GV->getName() == "llvm.global_dtors" && GV->use_empty()) { - SwitchToDataSection(StaticDtorsSection, 0); + SwitchToDataSection(TAI->getStaticDtorsSection()); EmitAlignment(2, 0); EmitXXStructorList(GV->getInitializer()); return true; @@ -274,6 +295,22 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { return false; } +/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each +/// global in the specified llvm.used list as being used with this directive. +void AsmPrinter::EmitLLVMUsedList(Constant *List) { + const char *Directive = TAI->getUsedDirective(); + + // Should be an array of 'sbyte*'. + ConstantArray *InitList = dyn_cast(List); + if (InitList == 0) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + O << Directive; + EmitConstantValueOnly(InitList->getOperand(i)); + O << "\n"; + } +} + /// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the /// function pointers, ignoring the init priority. void AsmPrinter::EmitXXStructorList(Constant *List) { @@ -292,27 +329,15 @@ void AsmPrinter::EmitXXStructorList(Constant *List) { } } -/// getPreferredAlignmentLog - Return the preferred alignment of the -/// specified global, returned in log form. This includes an explicitly -/// requested alignment (if the global has one). -unsigned AsmPrinter::getPreferredAlignmentLog(const GlobalVariable *GV) const { - const Type *ElemType = GV->getType()->getElementType(); - unsigned Alignment = TM.getTargetData()->getTypeAlignmentShift(ElemType); - if (GV->getAlignment() > (1U << Alignment)) - Alignment = Log2_32(GV->getAlignment()); - - if (GV->hasInitializer()) { - // Always round up alignment of global doubles to 8 bytes. - if (GV->getType()->getElementType() == Type::DoubleTy && Alignment < 3) - Alignment = 3; - if (Alignment < 4) { - // If the global is not external, see if it is large. If so, give it a - // larger alignment. - if (TM.getTargetData()->getTypeSize(ElemType) > 128) - Alignment = 4; // 16-byte alignment. - } - } - return Alignment; +/// getGlobalLinkName - Returns the asm/link name of of the specified +/// global variable. Should be overridden by each target asm printer to +/// generate the appropriate value. +const std::string AsmPrinter::getGlobalLinkName(const GlobalVariable *GV) const{ + std::string LinkName; + // Default action is to use a global symbol. + LinkName = TAI->getGlobalPrefix(); + LinkName += GV->getName(); + return LinkName; } // EmitAlignment - Emit an alignment directive to the specified power of two. @@ -320,22 +345,22 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { if (GV && GV->getAlignment()) NumBits = Log2_32(GV->getAlignment()); if (NumBits == 0) return; // No need to emit alignment. - if (AlignmentIsInBytes) NumBits = 1 << NumBits; - O << AlignDirective << NumBits << "\n"; + if (TAI->getAlignmentIsInBytes()) NumBits = 1 << NumBits; + O << TAI->getAlignDirective() << NumBits << "\n"; } /// EmitZeros - Emit a block of zeros. /// void AsmPrinter::EmitZeros(uint64_t NumZeros) const { if (NumZeros) { - if (ZeroDirective) { - O << ZeroDirective << NumZeros; - if (ZeroDirectiveSuffix) - O << ZeroDirectiveSuffix; + if (TAI->getZeroDirective()) { + O << TAI->getZeroDirective() << NumZeros; + if (TAI->getZeroDirectiveSuffix()) + O << TAI->getZeroDirectiveSuffix(); O << "\n"; } else { for (; NumZeros; --NumZeros) - O << Data8bitsDirective << "0\n"; + O << TAI->getData8bitsDirective() << "0\n"; } } } @@ -346,24 +371,30 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { if (CV->isNullValue() || isa(CV)) O << "0"; else if (const ConstantBool *CB = dyn_cast(CV)) { - assert(CB == ConstantBool::True); + assert(CB->getValue()); O << "1"; - } else if (const ConstantSInt *CI = dyn_cast(CV)) - if (((CI->getValue() << 32) >> 32) == CI->getValue()) - O << CI->getValue(); - else - O << (uint64_t)CI->getValue(); - else if (const ConstantUInt *CI = dyn_cast(CV)) - O << CI->getValue(); - else if (const GlobalValue *GV = dyn_cast(CV)) { + } else if (const ConstantInt *CI = dyn_cast(CV)) { + if (CI->getType()->isSigned()) { + if (((CI->getSExtValue() << 32) >> 32) == CI->getSExtValue()) + O << CI->getSExtValue(); + else + O << (uint64_t)CI->getSExtValue(); + } else + O << CI->getZExtValue(); + } else if (const GlobalValue *GV = dyn_cast(CV)) { // This is a constant address for a global variable or function. Use the // name of the variable or function as the address value, possibly // decorating it with GlobalVarAddrPrefix/Suffix or // FunctionAddrPrefix/Suffix (these all default to "" ) - if (isa(GV)) - O << FunctionAddrPrefix << Mang->getValueName(GV) << FunctionAddrSuffix; - else - O << GlobalVarAddrPrefix << Mang->getValueName(GV) << GlobalVarAddrSuffix; + if (isa(GV)) { + O << TAI->getFunctionAddrPrefix() + << Mang->getValueName(GV) + << TAI->getFunctionAddrSuffix(); + } else { + O << TAI->getGlobalVarAddrPrefix() + << Mang->getValueName(GV) + << TAI->getGlobalVarAddrSuffix(); + } } else if (const ConstantExpr *CE = dyn_cast(CV)) { const TargetData *TD = TM.getTargetData(); switch(CE->getOpcode()) { @@ -442,7 +473,7 @@ static void printAsCString(std::ostream &O, const ConstantArray *CVA, O << "\""; for (unsigned i = 0; i != LastElt; ++i) { unsigned char C = - (unsigned char)cast(CVA->getOperand(i))->getRawValue(); + (unsigned char)cast(CVA->getOperand(i))->getZExtValue(); if (C == '"') { O << "\\\""; @@ -473,12 +504,12 @@ static void printAsCString(std::ostream &O, const ConstantArray *CVA, /// void AsmPrinter::EmitString(const ConstantArray *CVA) const { unsigned NumElts = CVA->getNumOperands(); - if (AscizDirective && NumElts && - cast(CVA->getOperand(NumElts-1))->getRawValue() == 0) { - O << AscizDirective; + if (TAI->getAscizDirective() && NumElts && + cast(CVA->getOperand(NumElts-1))->getZExtValue() == 0) { + O << TAI->getAscizDirective(); printAsCString(O, CVA, NumElts-1); } else { - O << AsciiDirective; + O << TAI->getAsciiDirective(); printAsCString(O, CVA, NumElts); } O << "\n"; @@ -528,50 +559,50 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) { // precision... double Val = CFP->getValue(); if (CFP->getType() == Type::DoubleTy) { - if (Data64bitsDirective) - O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString - << " double value: " << Val << "\n"; + if (TAI->getData64bitsDirective()) + O << TAI->getData64bitsDirective() << DoubleToBits(Val) << "\t" + << TAI->getCommentString() << " double value: " << Val << "\n"; else if (TD->isBigEndian()) { - O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32) - << "\t" << CommentString << " double most significant word " - << Val << "\n"; - O << Data32bitsDirective << unsigned(DoubleToBits(Val)) - << "\t" << CommentString << " double least significant word " - << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val) >> 32) + << "\t" << TAI->getCommentString() + << " double most significant word " << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val)) + << "\t" << TAI->getCommentString() + << " double least significant word " << Val << "\n"; } else { - O << Data32bitsDirective << unsigned(DoubleToBits(Val)) - << "\t" << CommentString << " double least significant word " << Val - << "\n"; - O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32) - << "\t" << CommentString << " double most significant word " << Val - << "\n"; + O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val)) + << "\t" << TAI->getCommentString() + << " double least significant word " << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(DoubleToBits(Val) >> 32) + << "\t" << TAI->getCommentString() + << " double most significant word " << Val << "\n"; } return; } else { - O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString - << " float " << Val << "\n"; + O << TAI->getData32bitsDirective() << FloatToBits(Val) + << "\t" << TAI->getCommentString() << " float " << Val << "\n"; return; } } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) { if (const ConstantInt *CI = dyn_cast(CV)) { - uint64_t Val = CI->getRawValue(); + uint64_t Val = CI->getZExtValue(); - if (Data64bitsDirective) - O << Data64bitsDirective << Val << "\n"; + if (TAI->getData64bitsDirective()) + O << TAI->getData64bitsDirective() << Val << "\n"; else if (TD->isBigEndian()) { - O << Data32bitsDirective << unsigned(Val >> 32) - << "\t" << CommentString << " Double-word most significant word " - << Val << "\n"; - O << Data32bitsDirective << unsigned(Val) - << "\t" << CommentString << " Double-word least significant word " - << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(Val >> 32) + << "\t" << TAI->getCommentString() + << " Double-word most significant word " << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(Val) + << "\t" << TAI->getCommentString() + << " Double-word least significant word " << Val << "\n"; } else { - O << Data32bitsDirective << unsigned(Val) - << "\t" << CommentString << " Double-word least significant word " - << Val << "\n"; - O << Data32bitsDirective << unsigned(Val >> 32) - << "\t" << CommentString << " Double-word most significant word " - << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(Val) + << "\t" << TAI->getCommentString() + << " Double-word least significant word " << Val << "\n"; + O << TAI->getData32bitsDirective() << unsigned(Val >> 32) + << "\t" << TAI->getCommentString() + << " Double-word most significant word " << Val << "\n"; } return; } @@ -585,39 +616,43 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) { } const Type *type = CV->getType(); - switch (type->getTypeID()) { - case Type::BoolTyID: - case Type::UByteTyID: case Type::SByteTyID: - O << Data8bitsDirective; - break; - case Type::UShortTyID: case Type::ShortTyID: - O << Data16bitsDirective; - break; - case Type::PointerTyID: - if (TD->getPointerSize() == 8) { - assert(Data64bitsDirective && - "Target cannot handle 64-bit pointer exprs!"); - O << Data64bitsDirective; - break; - } - //Fall through for pointer size == int size - case Type::UIntTyID: case Type::IntTyID: - O << Data32bitsDirective; - break; - case Type::ULongTyID: case Type::LongTyID: - assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!"); - O << Data64bitsDirective; - break; - case Type::FloatTyID: case Type::DoubleTyID: - assert (0 && "Should have already output floating point constant."); - default: - assert (0 && "Can't handle printing this type of thing"); - break; - } + printDataDirective(type); EmitConstantValueOnly(CV); O << "\n"; } +void +AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { + // Target doesn't support this yet! + abort(); +} + +/// PrintSpecial - Print information related to the specified machine instr +/// that is independent of the operand, and may be independent of the instr +/// itself. This can be useful for portably encoding the comment character +/// or other bits of target-specific knowledge into the asmstrings. The +/// syntax used is ${:comment}. Targets can override this to add support +/// for their own strange codes. +void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) { + if (!strcmp(Code, "private")) { + O << TAI->getPrivateGlobalPrefix(); + } else if (!strcmp(Code, "comment")) { + O << TAI->getCommentString(); + } else if (!strcmp(Code, "uid")) { + // Assign a unique ID to this machine instruction. + static const MachineInstr *LastMI = 0; + static unsigned Counter = 0U-1; + // If this is a new machine instruction, bump the counter. + if (LastMI != MI) { ++Counter; LastMI = MI; } + O << Counter; + } else { + std::cerr << "Unknown special formatter '" << Code + << "' for machine instr: " << *MI; + exit(1); + } +} + + /// printInlineAsm - This method formats and prints the specified machine /// instruction that is an inline asm. void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { @@ -625,7 +660,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { // Count the number of register definitions. unsigned NumDefs = 0; - for (; MI->getOperand(NumDefs).isDef(); ++NumDefs) + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) assert(NumDefs != NumOperands-1 && "No asm string?"); assert(MI->getOperand(NumDefs).isExternalSymbol() && "No asm string?"); @@ -639,7 +675,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { return; } - O << InlineAsmStart << "\n\t"; + O << TAI->getInlineAsmStart() << "\n\t"; // The variant of the current asmprinter: FIXME: change. int AsmPrinterVariant = 0; @@ -666,12 +702,45 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { break; case '$': { ++LastEmitted; // Consume '$' character. - if (*LastEmitted == '$') { // $$ -> $ + bool Done = true; + + // Handle escapes. + switch (*LastEmitted) { + default: Done = false; break; + case '$': // $$ -> $ if (CurVariant == -1 || CurVariant == AsmPrinterVariant) O << '$'; ++LastEmitted; // Consume second '$' character. break; + case '(': // $( -> same as GCC's { character. + ++LastEmitted; // Consume '(' character. + if (CurVariant != -1) { + std::cerr << "Nested variants found in inline asm string: '" + << AsmStr << "'\n"; + exit(1); + } + CurVariant = 0; // We're in the first variant now. + break; + case '|': + ++LastEmitted; // consume '|' character. + if (CurVariant == -1) { + std::cerr << "Found '|' character outside of variant in inline asm " + << "string: '" << AsmStr << "'\n"; + exit(1); + } + ++CurVariant; // We're in the next variant. + break; + case ')': // $) -> same as GCC's } char. + ++LastEmitted; // consume ')' character. + if (CurVariant == -1) { + std::cerr << "Found '}' character outside of variant in inline asm " + << "string: '" << AsmStr << "'\n"; + exit(1); + } + CurVariant = -1; + break; } + if (Done) break; bool HasCurlyBraces = false; if (*LastEmitted == '{') { // ${variable} @@ -758,36 +827,9 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { } break; } - case '{': - ++LastEmitted; // Consume '{' character. - if (CurVariant != -1) { - std::cerr << "Nested variants found in inline asm string: '" - << AsmStr << "'\n"; - exit(1); - } - CurVariant = 0; // We're in the first variant now. - break; - case '|': - ++LastEmitted; // consume '|' character. - if (CurVariant == -1) { - std::cerr << "Found '|' character outside of variant in inline asm " - << "string: '" << AsmStr << "'\n"; - exit(1); - } - ++CurVariant; // We're in the next variant. - break; - case '}': - ++LastEmitted; // consume '}' character. - if (CurVariant == -1) { - std::cerr << "Found '}' character outside of variant in inline asm " - << "string: '" << AsmStr << "'\n"; - exit(1); - } - CurVariant = -1; - break; } } - O << "\n\t" << InlineAsmEnd << "\n"; + O << "\n\t" << TAI->getInlineAsmEnd() << "\n"; } /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM @@ -811,10 +853,60 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, void AsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB, bool printColon, bool printComment) const { - O << PrivateGlobalPrefix << "BB" << FunctionNumber << "_" + O << TAI->getPrivateGlobalPrefix() << "BB" << FunctionNumber << "_" << MBB->getNumber(); if (printColon) O << ':'; - if (printComment) - O << '\t' << CommentString << MBB->getBasicBlock()->getName(); + if (printComment && MBB->getBasicBlock()) + O << '\t' << TAI->getCommentString() << MBB->getBasicBlock()->getName(); +} + +/// printSetLabel - This method prints a set label for the specified +/// MachineBasicBlock +void AsmPrinter::printSetLabel(unsigned uid, + const MachineBasicBlock *MBB) const { + if (!TAI->getSetDirective()) + return; + + O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; + printBasicBlockLabel(MBB, false, false); + O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << uid << '\n'; +} + +/// printDataDirective - This method prints the asm directive for the +/// specified type. +void AsmPrinter::printDataDirective(const Type *type) { + const TargetData *TD = TM.getTargetData(); + switch (type->getTypeID()) { + case Type::BoolTyID: + case Type::UByteTyID: case Type::SByteTyID: + O << TAI->getData8bitsDirective(); + break; + case Type::UShortTyID: case Type::ShortTyID: + O << TAI->getData16bitsDirective(); + break; + case Type::PointerTyID: + if (TD->getPointerSize() == 8) { + assert(TAI->getData64bitsDirective() && + "Target cannot handle 64-bit pointer exprs!"); + O << TAI->getData64bitsDirective(); + break; + } + //Fall through for pointer size == int size + case Type::UIntTyID: case Type::IntTyID: + O << TAI->getData32bitsDirective(); + break; + case Type::ULongTyID: case Type::LongTyID: + assert(TAI->getData64bitsDirective() && + "Target cannot handle 64-bit constant exprs!"); + O << TAI->getData64bitsDirective(); + break; + case Type::FloatTyID: case Type::DoubleTyID: + assert (0 && "Should have already output floating point constant."); + default: + assert (0 && "Can't handle printing this type of thing"); + break; + } }