diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-06 15:52:58 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-06 15:52:58 +0000 |
commit | 9f4a1da9a0a56a0b0a7f8249f34b3cdea6179c41 (patch) | |
tree | 0dd020f28a4846707f8d60717d9b2921ea187bd8 /lib/CodeGen | |
parent | b5efedaf2ab20d844d5a21cdef76b55acbf4f01c (diff) | |
download | src-test2-9f4a1da9a0a56a0b0a7f8249f34b3cdea6179c41.tar.gz src-test2-9f4a1da9a0a56a0b0a7f8249f34b3cdea6179c41.zip |
Notes
Diffstat (limited to 'lib/CodeGen')
27 files changed, 1557 insertions, 1608 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 625a2b95f205..c86e2411d303 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -13,11 +13,9 @@ #define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Constants.h" +#include "DwarfDebug.h" +#include "DwarfException.h" #include "llvm/Module.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -27,50 +25,59 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" -#include "llvm/Support/FormattedStream.h" -#include <cerrno> using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); char AsmPrinter::ID = 0; -AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, - MCStreamer &Streamer) - : MachineFunctionPass(&ID), O(o), - TM(tm), MAI(tm.getMCAsmInfo()), TRI(tm.getRegisterInfo()), +typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type; +static gcp_map_type &getGCMap(void *&P) { + if (P == 0) + P = new gcp_map_type(); + return *(gcp_map_type*)P; +} + + +AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) + : MachineFunctionPass(&ID), + TM(tm), MAI(tm.getMCAsmInfo()), OutContext(Streamer.getContext()), OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { - DW = 0; MMI = 0; + DD = 0; DE = 0; MMI = 0; LI = 0; + GCMetadataPrinters = 0; VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { - for (gcp_iterator I = GCMetadataPrinters.begin(), - E = GCMetadataPrinters.end(); I != E; ++I) - delete I->second; + assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized"); + + if (GCMetadataPrinters != 0) { + gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); + + for (gcp_map_type::iterator I = GCMap.begin(), E = GCMap.end(); I != E; ++I) + delete I->second; + delete &GCMap; + GCMetadataPrinters = 0; + } delete &OutStreamer; } @@ -85,18 +92,25 @@ TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { return TM.getTargetLowering()->getObjFileLowering(); } + +/// getTargetData - Return information about data layout. +const TargetData &AsmPrinter::getTargetData() const { + return *TM.getTargetData(); +} + /// getCurrentSection() - Return the current section we are emitting to. const MCSection *AsmPrinter::getCurrentSection() const { return OutStreamer.getCurrentSection(); } + void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); AU.addRequired<MachineModuleInfo>(); AU.addRequired<GCModuleInfo>(); - if (VerboseAsm) + if (isVerbose()) AU.addRequired<MachineLoopInfo>(); } @@ -124,17 +138,22 @@ bool AsmPrinter::doInitialization(Module &M) { assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) - MP->beginAssembly(O, *this, *MAI); - - if (!M.getModuleInlineAsm().empty()) - O << MAI->getCommentString() << " Start of file scope inline assembly\n" - << M.getModuleInlineAsm() - << '\n' << MAI->getCommentString() - << " End of file scope inline assembly\n"; + MP->beginAssembly(*this); - DW = getAnalysisIfAvailable<DwarfWriter>(); - if (DW) - DW->BeginModule(&M, MMI, O, this, MAI); + // Emit module-level inline asm if it exists. + if (!M.getModuleInlineAsm().empty()) { + OutStreamer.AddComment("Start of file scope inline assembly"); + OutStreamer.AddBlankLine(); + EmitInlineAsm(M.getModuleInlineAsm(), 0/*no loc cookie*/); + OutStreamer.AddComment("End of file scope inline assembly"); + OutStreamer.AddBlankLine(); + } + + if (MAI->doesSupportDebugInformation()) + DD = new DwarfDebug(this, &M); + + if (MAI->doesSupportExceptionHandling()) + DE = new DwarfException(this); return false; } @@ -161,7 +180,7 @@ void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const { // .linkonce discard // FIXME: It would be nice to use .linkonce samesize for non-common // globals. - O << LinkOnce; + OutStreamer.EmitRawText(StringRef(LinkOnce)); } else { // .weak _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); @@ -210,7 +229,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (GVKind.isCommon() || GVKind.isBSSLocal()) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - if (VerboseAsm) { + if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); OutStreamer.GetCommentOS() << '\n'; @@ -263,7 +282,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { EmitLinkage(GV->getLinkage(), GVSym); EmitAlignment(AlignLog, GV); - if (VerboseAsm) { + if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); OutStreamer.GetCommentOS() << '\n'; @@ -297,7 +316,7 @@ void AsmPrinter::EmitFunctionHeader() { if (MAI->hasDotTypeDotSizeDirective()) OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); - if (VerboseAsm) { + if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), F, /*PrintType=*/false, F->getParent()); OutStreamer.GetCommentOS() << '\n'; @@ -319,13 +338,17 @@ void AsmPrinter::EmitFunctionHeader() { // Add some workaround for linkonce linkage on Cygwin\MinGW. if (MAI->getLinkOnceDirective() != 0 && - (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) + (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) { // FIXME: What is this? - O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n"; + MCSymbol *FakeStub = + OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+ + CurrentFnSym->getName()); + OutStreamer.EmitLabel(FakeStub); + } // Emit pre-function debug and/or EH information. - if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) - DW->BeginFunction(MF); + if (DE) DE->BeginFunction(MF); + if (DD) DD->beginFunction(MF); } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the @@ -389,6 +412,28 @@ static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { } } +/// EmitImplicitDef - This method emits the specified machine instruction +/// that is an implicit def. +static void EmitImplicitDef(const MachineInstr *MI, AsmPrinter &AP) { + unsigned RegNo = MI->getOperand(0).getReg(); + AP.OutStreamer.AddComment(Twine("implicit-def: ") + + AP.TM.getRegisterInfo()->getName(RegNo)); + AP.OutStreamer.AddBlankLine(); +} + +static void EmitKill(const MachineInstr *MI, AsmPrinter &AP) { + std::string Str = "kill:"; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &Op = MI->getOperand(i); + assert(Op.isReg() && "KILL instruction must have only register operands"); + Str += ' '; + Str += AP.TM.getRegisterInfo()->getName(Op.getReg()); + Str += (Op.isDef() ? "<def>" : "<kill>"); + } + AP.OutStreamer.AddComment(Str); + AP.OutStreamer.AddBlankLine(); +} + /// EmitFunctionBody - This method emits the body and trailer for a @@ -397,6 +442,8 @@ void AsmPrinter::EmitFunctionBody() { // Emit target-specific gunk before the function body. EmitFunctionBodyStart(); + bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo(); + // Print out code for the function. bool HasAnyRealCode = false; for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); @@ -411,34 +458,34 @@ void AsmPrinter::EmitFunctionBody() { ++EmittedInsts; - // FIXME: Clean up processDebugLoc. - processDebugLoc(II, true); + if (ShouldPrintDebugScopes) + DD->beginScope(II); - if (VerboseAsm) + if (isVerbose()) EmitComments(*II, OutStreamer.GetCommentOS()); switch (II->getOpcode()) { case TargetOpcode::DBG_LABEL: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: - printLabelInst(II); + OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); break; case TargetOpcode::INLINEASM: - printInlineAsm(II); + EmitInlineAsm(II); break; case TargetOpcode::IMPLICIT_DEF: - printImplicitDef(II); + if (isVerbose()) EmitImplicitDef(II, *this); break; case TargetOpcode::KILL: - printKill(II); + if (isVerbose()) EmitKill(II, *this); break; default: EmitInstruction(II); break; } - // FIXME: Clean up processDebugLoc. - processDebugLoc(II, false); + if (ShouldPrintDebugScopes) + DD->endScope(II); } } @@ -451,12 +498,25 @@ void AsmPrinter::EmitFunctionBody() { // Emit target-specific gunk after the function body. EmitFunctionBodyEnd(); - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; + // If the target wants a .size directive for the size of the function, emit + // it. + if (MAI->hasDotTypeDotSizeDirective()) { + // Create a symbol for the end of function, so we can get the size as + // difference between the function label and the temp label. + MCSymbol *FnEndLabel = OutContext.CreateTempSymbol(); + OutStreamer.EmitLabel(FnEndLabel); + + const MCExpr *SizeExp = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext), + MCSymbolRefExpr::Create(CurrentFnSym, OutContext), + OutContext); + OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); + } // Emit post-function debug information. - if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) - DW->EndFunction(MF); + if (DD) DD->endFunction(MF); + if (DE) DE->EndFunction(); + MMI->EndFunction(); // Print out jump tables referenced by the function. EmitJumpTableInfo(); @@ -471,9 +531,15 @@ bool AsmPrinter::doFinalization(Module &M) { I != E; ++I) EmitGlobalVariable(I); - // Emit final debug information. - if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) - DW->EndModule(); + // Finalize debug and EH information. + if (DE) { + DE->EndModule(); + delete DE; DE = 0; + } + if (DD) { + DD->endModule(); + delete DD; DD = 0; + } // If the target wants to know about weak references, print them all. if (MAI->getWeakRefDirective()) { @@ -523,7 +589,7 @@ bool AsmPrinter::doFinalization(Module &M) { assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) - MP->finishAssembly(O, *this, *MAI); + MP->finishAssembly(*this); // If we don't have any trampolines, then we don't require stack memory // to be executable. Some targets have a directive to declare this. @@ -537,7 +603,7 @@ bool AsmPrinter::doFinalization(Module &M) { EmitEndOfAsmFile(M); delete Mang; Mang = 0; - DW = 0; MMI = 0; + MMI = 0; OutStreamer.Finish(); return false; @@ -548,7 +614,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { // Get the function symbol. CurrentFnSym = Mang->getSymbol(MF.getFunction()); - if (VerboseAsm) + if (isVerbose()) LI = &getAnalysis<MachineLoopInfo>(); } @@ -636,7 +702,7 @@ void AsmPrinter::EmitConstantPool() { Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); // Emit the label with a comment on it. - if (VerboseAsm) { + if (isVerbose()) { OutStreamer.GetCommentOS() << "constant pool "; WriteTypeSymbolic(OutStreamer.GetCommentOS(), CPE.getType(), MF->getFunction()->getParent()); @@ -896,12 +962,6 @@ void AsmPrinter::EmitInt32(int Value) const { OutStreamer.EmitIntValue(Value, 4, 0/*addrspace*/); } -/// EmitInt64 - Emit a long long directive and value. -/// -void AsmPrinter::EmitInt64(uint64_t Value) const { - OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/); -} - /// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size /// in bytes of the directive is specified by Size and Hi/Lo specify the /// labels. This implicitly uses .set if it is available. @@ -919,9 +979,7 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, } // Otherwise, emit with .set (aka assignment). - MCSymbol *SetLabel = - OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + - "set" + Twine(SetCounter++)); + MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++); OutStreamer.EmitAssignment(SetLabel, Diff); OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/); } @@ -1156,7 +1214,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, // FP Constants are printed as integer constants to avoid losing // precision. if (CFP->getType()->isDoubleTy()) { - if (AP.VerboseAsm) { + if (AP.isVerbose()) { double Val = CFP->getValueAPF().convertToDouble(); AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; } @@ -1167,7 +1225,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, } if (CFP->getType()->isFloatTy()) { - if (AP.VerboseAsm) { + if (AP.isVerbose()) { float Val = CFP->getValueAPF().convertToFloat(); AP.OutStreamer.GetCommentOS() << "float " << Val << '\n'; } @@ -1181,7 +1239,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, // api needed to prevent premature destruction APInt API = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = API.getRawData(); - if (AP.VerboseAsm) { + if (AP.isVerbose()) { // Convert to double so we can print the approximate val as a comment. APFloat DoubleVal = CFP->getValueAPF(); bool ignored; @@ -1252,7 +1310,7 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { case 2: case 4: case 8: - if (VerboseAsm) + if (isVerbose()) OutStreamer.GetCommentOS() << format("0x%llx\n", CI->getZExtValue()); OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace); return; @@ -1295,297 +1353,31 @@ void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); } -/// 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) const { - if (!strcmp(Code, "private")) { - O << MAI->getPrivateGlobalPrefix(); - } else if (!strcmp(Code, "comment")) { - if (VerboseAsm) - O << MAI->getCommentString(); - } else if (!strcmp(Code, "uid")) { - // Comparing the address of MI isn't sufficient, because machineinstrs may - // be allocated to the same address across functions. - const Function *ThisF = MI->getParent()->getParent()->getFunction(); - - // If this is a new LastFn instruction, bump the counter. - if (LastMI != MI || LastFn != ThisF) { - ++Counter; - LastMI = MI; - LastFn = ThisF; - } - O << Counter; - } else { - std::string msg; - raw_string_ostream Msg(msg); - Msg << "Unknown special formatter '" << Code - << "' for machine instr: " << *MI; - llvm_report_error(Msg.str()); - } -} - -/// processDebugLoc - Processes the debug information of each machine -/// instruction's DebugLoc. -void AsmPrinter::processDebugLoc(const MachineInstr *MI, - bool BeforePrintingInsn) { - if (!MAI || !DW || !MAI->doesSupportDebugInformation() - || !DW->ShouldEmitDwarfDebug()) - return; - - if (!BeforePrintingInsn) - // After printing instruction - DW->EndScope(MI); - else - DW->BeginScope(MI); -} - - -/// printInlineAsm - This method formats and prints the specified machine -/// instruction that is an inline asm. -void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { - unsigned NumOperands = MI->getNumOperands(); - - // Count the number of register definitions. - unsigned NumDefs = 0; - for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); - ++NumDefs) - assert(NumDefs != NumOperands-1 && "No asm string?"); - - assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); - - // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. - const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); - - O << '\t'; - - // If this asmstr is empty, just print the #APP/#NOAPP markers. - // These are useful to see where empty asm's wound up. - if (AsmStr[0] == 0) { - O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; - O << MAI->getCommentString() << MAI->getInlineAsmEnd() << '\n'; - return; - } - - O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t"; - - // The variant of the current asmprinter. - int AsmPrinterVariant = MAI->getAssemblerDialect(); - - int CurVariant = -1; // The number of the {.|.|.} region we are in. - const char *LastEmitted = AsmStr; // One past the last character emitted. - - while (*LastEmitted) { - switch (*LastEmitted) { - default: { - // Not a special case, emit the string section literally. - const char *LiteralEnd = LastEmitted+1; - while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && - *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') - ++LiteralEnd; - if (CurVariant == -1 || CurVariant == AsmPrinterVariant) - O.write(LastEmitted, LiteralEnd-LastEmitted); - LastEmitted = LiteralEnd; - break; - } - case '\n': - ++LastEmitted; // Consume newline character. - O << '\n'; // Indent code with newline. - break; - case '$': { - ++LastEmitted; // Consume '$' character. - 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) { - llvm_report_error("Nested variants found in inline asm string: '" - + std::string(AsmStr) + "'"); - } - CurVariant = 0; // We're in the first variant now. - break; - case '|': - ++LastEmitted; // consume '|' character. - if (CurVariant == -1) - O << '|'; // this is gcc's behavior for | outside a variant - else - ++CurVariant; // We're in the next variant. - break; - case ')': // $) -> same as GCC's } char. - ++LastEmitted; // consume ')' character. - if (CurVariant == -1) - O << '}'; // this is gcc's behavior for } outside a variant - else - CurVariant = -1; - break; - } - if (Done) break; - - bool HasCurlyBraces = false; - if (*LastEmitted == '{') { // ${variable} - ++LastEmitted; // Consume '{' character. - HasCurlyBraces = true; - } - - // If we have ${:foo}, then this is not a real operand reference, it is a - // "magic" string reference, just like in .td files. Arrange to call - // PrintSpecial. - if (HasCurlyBraces && *LastEmitted == ':') { - ++LastEmitted; - const char *StrStart = LastEmitted; - const char *StrEnd = strchr(StrStart, '}'); - if (StrEnd == 0) { - llvm_report_error("Unterminated ${:foo} operand in inline asm string: '" - + std::string(AsmStr) + "'"); - } - - std::string Val(StrStart, StrEnd); - PrintSpecial(MI, Val.c_str()); - LastEmitted = StrEnd+1; - break; - } - - const char *IDStart = LastEmitted; - char *IDEnd; - errno = 0; - long Val = strtol(IDStart, &IDEnd, 10); // We only accept numbers for IDs. - if (!isdigit(*IDStart) || (Val == 0 && errno == EINVAL)) { - llvm_report_error("Bad $ operand number in inline asm string: '" - + std::string(AsmStr) + "'"); - } - LastEmitted = IDEnd; - - char Modifier[2] = { 0, 0 }; - - if (HasCurlyBraces) { - // If we have curly braces, check for a modifier character. This - // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. - if (*LastEmitted == ':') { - ++LastEmitted; // Consume ':' character. - if (*LastEmitted == 0) { - llvm_report_error("Bad ${:} expression in inline asm string: '" - + std::string(AsmStr) + "'"); - } - - Modifier[0] = *LastEmitted; - ++LastEmitted; // Consume modifier character. - } - - if (*LastEmitted != '}') { - llvm_report_error("Bad ${} expression in inline asm string: '" - + std::string(AsmStr) + "'"); - } - ++LastEmitted; // Consume '}' character. - } - - if ((unsigned)Val >= NumOperands-1) { - llvm_report_error("Invalid $ operand number in inline asm string: '" - + std::string(AsmStr) + "'"); - } - - // Okay, we finally have a value number. Ask the target to print this - // operand! - if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { - unsigned OpNo = 1; - - bool Error = false; - - // Scan to find the machine operand number for the operand. - for (; Val; --Val) { - if (OpNo >= MI->getNumOperands()) break; - unsigned OpFlags = MI->getOperand(OpNo).getImm(); - OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; - } - - if (OpNo >= MI->getNumOperands()) { - Error = true; - } else { - unsigned OpFlags = MI->getOperand(OpNo).getImm(); - ++OpNo; // Skip over the ID number. - - if (Modifier[0] == 'l') // labels are target independent - O << *MI->getOperand(OpNo).getMBB()->getSymbol(); - else { - AsmPrinter *AP = const_cast<AsmPrinter*>(this); - if ((OpFlags & 7) == 4) { - Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, - Modifier[0] ? Modifier : 0); - } else { - Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, - Modifier[0] ? Modifier : 0); - } - } - } - if (Error) { - std::string msg; - raw_string_ostream Msg(msg); - Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; - MI->print(Msg); - llvm_report_error(Msg.str()); - } - } - break; - } - } - } - O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd(); - OutStreamer.AddBlankLine(); -} - -/// printImplicitDef - This method prints the specified machine instruction -/// that is an implicit def. -void AsmPrinter::printImplicitDef(const MachineInstr *MI) const { - if (!VerboseAsm) return; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " implicit-def: " - << TRI->getName(MI->getOperand(0).getReg()); - OutStreamer.AddBlankLine(); +void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const { + if (Offset > 0) + OS << '+' << Offset; + else if (Offset < 0) + OS << Offset; } -void AsmPrinter::printKill(const MachineInstr *MI) const { - if (!VerboseAsm) return; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " kill:"; - for (unsigned n = 0, e = MI->getNumOperands(); n != e; ++n) { - const MachineOperand &op = MI->getOperand(n); - assert(op.isReg() && "KILL instruction must have only register operands"); - O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "<def>" : "<kill>"); - } - OutStreamer.AddBlankLine(); -} +//===----------------------------------------------------------------------===// +// Symbol Lowering Routines. +//===----------------------------------------------------------------------===// -/// printLabel - This method prints a local label used by debug and -/// exception handling tables. -void AsmPrinter::printLabelInst(const MachineInstr *MI) const { - OutStreamer.EmitLabel(MI->getOperand(0).getMCSymbol()); +/// GetTempSymbol - Return the MCSymbol corresponding to the assembler +/// temporary label with the specified stem and unique ID. +MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const { + return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + + Name + Twine(ID)); } -/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM -/// instruction, using the specified assembler variant. Targets should -/// override this to format as appropriate. -bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode) { - // Target doesn't support this yet! - return true; +/// GetTempSymbol - Return an assembler temporary label with the specified +/// stem. +MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const { + return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+ + Name); } -bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode) { - // Target doesn't support this yet! - return true; -} MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { return MMI->getAddrLabelSymbol(BA->getBasicBlock()); @@ -1663,10 +1455,10 @@ static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, } } -/// PrintBasicBlockLoopComments - Pretty-print comments for basic blocks. -static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB, - const MachineLoopInfo *LI, - const AsmPrinter &AP) { +/// EmitBasicBlockLoopComments - Pretty-print comments for basic blocks. +static void EmitBasicBlockLoopComments(const MachineBasicBlock &MBB, + const MachineLoopInfo *LI, + const AsmPrinter &AP) { // Add loop depth information const MachineLoop *Loop = LI->getLoopFor(&MBB); if (Loop == 0) return; @@ -1716,7 +1508,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { // the references were generated. if (MBB->hasAddressTaken()) { const BasicBlock *BB = MBB->getBasicBlock(); - if (VerboseAsm) + if (isVerbose()) OutStreamer.AddComment("Block address taken"); std::vector<MCSymbol*> Syms = MMI->getAddrLabelSymbolToEmit(BB); @@ -1727,22 +1519,23 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { // Print the main label for the block. if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) { - if (VerboseAsm) { - // NOTE: Want this comment at start of line. - O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; + if (isVerbose() && OutStreamer.hasRawTextSupport()) { if (const BasicBlock *BB = MBB->getBasicBlock()) if (BB->hasName()) OutStreamer.AddComment("%" + BB->getName()); - PrintBasicBlockLoopComments(*MBB, LI, *this); - OutStreamer.AddBlankLine(); + EmitBasicBlockLoopComments(*MBB, LI, *this); + + // NOTE: Want this comment at start of line, don't emit with AddComment. + OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" + + Twine(MBB->getNumber()) + ":"); } } else { - if (VerboseAsm) { + if (isVerbose()) { if (const BasicBlock *BB = MBB->getBasicBlock()) if (BB->hasName()) OutStreamer.AddComment("%" + BB->getName()); - PrintBasicBlockLoopComments(*MBB, LI, *this); + EmitBasicBlockLoopComments(*MBB, LI, *this); } OutStreamer.EmitLabel(MBB->getSymbol()); @@ -1766,18 +1559,11 @@ void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const { OutStreamer.EmitSymbolAttribute(Sym, Attr); } -void AsmPrinter::printOffset(int64_t Offset) const { - if (Offset > 0) - O << '+' << Offset; - else if (Offset < 0) - O << Offset; -} - /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. -bool AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) - const { +bool AsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. if (MBB->isLandingPad() || MBB->pred_empty()) @@ -1809,9 +1595,10 @@ bool AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { if (!S->usesMetadata()) return 0; - - gcp_iterator GCPI = GCMetadataPrinters.find(S); - if (GCPI != GCMetadataPrinters.end()) + + gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); + gcp_map_type::iterator GCPI = GCMap.find(S); + if (GCPI != GCMap.end()) return GCPI->second; const char *Name = S->getName().c_str(); @@ -1822,7 +1609,7 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { if (strcmp(Name, I->getName()) == 0) { GCMetadataPrinter *GMP = I->instantiate(); GMP->S = S; - GCMetadataPrinters.insert(std::make_pair(S, GMP)); + GCMap.insert(std::make_pair(S, GMP)); return GMP; } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp new file mode 100644 index 000000000000..b310578584bc --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -0,0 +1,279 @@ +//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Dwarf emissions parts of AsmPrinter. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Dwarf.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Dwarf Emission Helper Routines +//===----------------------------------------------------------------------===// + +/// EmitSLEB128 - emit the specified signed leb128 value. +void AsmPrinter::EmitSLEB128(int Value, const char *Desc) const { + if (isVerbose() && Desc) + OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + // FIXME: MCize. + OutStreamer.EmitRawText("\t.sleb128\t" + Twine(Value)); + return; + } + + // If we don't have .sleb128, emit as .bytes. + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (IsMore); +} + +/// EmitULEB128 - emit the specified signed leb128 value. +void AsmPrinter::EmitULEB128(unsigned Value, const char *Desc, + unsigned PadTo) const { + if (isVerbose() && Desc) + OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128() && PadTo == 0) { + // FIXME: MCize. + OutStreamer.EmitRawText("\t.uleb128\t" + Twine(Value)); + return; + } + + // If we don't have .uleb128 or we want to emit padding, emit as .bytes. + do { + unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); + Value >>= 7; + if (Value || PadTo != 0) Byte |= 0x80; + OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (Value); + + if (PadTo) { + if (PadTo > 1) + OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); + OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); + } +} + +/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. +void AsmPrinter::EmitCFAByte(unsigned Val) const { + if (isVerbose()) { + if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) + OutStreamer.AddComment("DW_CFA_offset + Reg (" + + Twine(Val-dwarf::DW_CFA_offset) + ")"); + else + OutStreamer.AddComment(dwarf::CallFrameString(Val)); + } + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: return "absptr"; + case dwarf::DW_EH_PE_omit: return "omit"; + case dwarf::DW_EH_PE_pcrel: return "pcrel"; + case dwarf::DW_EH_PE_udata4: return "udata4"; + case dwarf::DW_EH_PE_udata8: return "udata8"; + case dwarf::DW_EH_PE_sdata4: return "sdata4"; + case dwarf::DW_EH_PE_sdata8: return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return "<unknown encoding>"; +} + + +/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an +/// encoding. If verbose assembly output is enabled, we output comments +/// describing the encoding. Desc is an optional string saying what the +/// encoding is specifying (e.g. "LSDA"). +void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { + if (isVerbose()) { + if (Desc != 0) + OutStreamer.AddComment(Twine(Desc)+" Encoding = " + + Twine(DecodeDWARFEncoding(Val))); + else + OutStreamer.AddComment(Twine("Encoding = ") + + DecodeDWARFEncoding(Val)); + } + + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// GetSizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + default: assert(0 && "Invalid encoded value."); + case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize(); + case dwarf::DW_EH_PE_udata2: return 2; + case dwarf::DW_EH_PE_udata4: return 4; + case dwarf::DW_EH_PE_udata8: return 8; + } +} + +void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + const MCExpr *Exp = + TLOF.getExprForDwarfReference(Sym, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); +} + +void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + const MCExpr *Exp = + TLOF.getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); +} + +/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its +/// section. This can be done with a special directive if the target supports +/// it (e.g. cygwin) or by emitting it as an offset from a label at the start +/// of the section. +/// +/// SectionLabel is a temporary label emitted at the start of the section that +/// Label lives in. +void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *SectionLabel) const { + // On COFF targets, we have to emit the special .secrel32 directive. + if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { + // FIXME: MCize. + OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName())); + return; + } + + // Get the section that we're referring to, based on SectionLabel. + const MCSection &Section = SectionLabel->getSection(); + + // If Label has already been emitted, verify that it is in the same section as + // section label for sanity. + assert((!Label->isInSection() || &Label->getSection() == &Section) && + "Section offset using wrong section base for label"); + + // If the section in question will end up with an address of 0 anyway, we can + // just emit an absolute reference to save a relocation. + if (Section.isBaseAddressKnownZero()) { + OutStreamer.EmitSymbolValue(Label, 4, 0/*AddrSpace*/); + return; + } + + // Otherwise, emit it as a label difference from the start of the section. + EmitLabelDifference(Label, SectionLabel, 4); +} + +//===----------------------------------------------------------------------===// +// Dwarf Lowering Routines +//===----------------------------------------------------------------------===// + + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +void AsmPrinter::EmitFrameMoves(const std::vector<MachineMove> &Moves, + MCSymbol *BaseLabel, bool isEH) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + + int stackGrowth = TM.getTargetData()->getPointerSize(); + if (TM.getFrameInfo()->getStackGrowthDirection() != + TargetFrameInfo::StackGrowsUp) + stackGrowth *= -1; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + MCSymbol *Label = Move.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabel && Label) { + MCSymbol *ThisSym = Label; + if (ThisSym != BaseLabel) { + EmitCFAByte(dwarf::DW_CFA_advance_loc4); + EmitLabelDifference(ThisSym, BaseLabel, 4); + BaseLabel = ThisSym; + } + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); + } else { + EmitCFAByte(dwarf::DW_CFA_def_cfa); + EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); + } + + EmitULEB128(-Src.getOffset(), "Offset"); + continue; + } + + if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + EmitCFAByte(dwarf::DW_CFA_def_cfa_register); + EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); + continue; + } + + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); + EmitULEB128(Reg, "Reg"); + EmitSLEB128(Offset, "Offset"); + } else if (Reg < 64) { + EmitCFAByte(dwarf::DW_CFA_offset + Reg); + EmitULEB128(Offset, "Offset"); + } else { + EmitCFAByte(dwarf::DW_CFA_offset_extended); + EmitULEB128(Reg, "Reg"); + EmitULEB128(Offset, "Offset"); + } + } +} diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp new file mode 100644 index 000000000000..255bcd413f22 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -0,0 +1,357 @@ +//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the inline assembler pieces of the AsmPrinter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/InlineAsm.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCParser/AsmParser.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. +void AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const { + assert(!Str.empty() && "Can't emit empty inline asm block"); + + // Remember if the buffer is nul terminated or not so we can avoid a copy. + bool isNullTerminated = Str.back() == 0; + if (isNullTerminated) + Str = Str.substr(0, Str.size()-1); + + // If the output streamer is actually a .s file, just emit the blob textually. + // This is useful in case the asm parser doesn't handle something but the + // system assembler does. + if (OutStreamer.hasRawTextSupport()) { + OutStreamer.EmitRawText(Str); + return; + } + + SourceMgr SrcMgr; + + // If the current LLVMContext has an inline asm handler, set it in SourceMgr. + LLVMContext &LLVMCtx = MMI->getModule()->getContext(); + bool HasDiagHandler = false; + if (void *DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler()) { + SrcMgr.setDiagHandler((SourceMgr::DiagHandlerTy)(intptr_t)DiagHandler, + LLVMCtx.getInlineAsmDiagnosticContext(), LocCookie); + HasDiagHandler = true; + } + + MemoryBuffer *Buffer; + if (isNullTerminated) + Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); + else + Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); + + // Tell SrcMgr about this buffer, it takes ownership of the buffer. + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + + AsmParser Parser(SrcMgr, OutContext, OutStreamer, *MAI); + OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(Parser)); + if (!TAP) + llvm_report_error("Inline asm not supported by this streamer because" + " we don't have an asm parser for this target\n"); + Parser.setTargetParser(*TAP.get()); + + // Don't implicitly switch to the text section before the asm. + int Res = Parser.Run(/*NoInitialTextSection*/ true, + /*NoFinalize*/ true); + if (Res && !HasDiagHandler) + llvm_report_error("Error parsing inline asm\n"); +} + + +/// EmitInlineAsm - This method formats and emits the specified machine +/// instruction that is an inline asm. +void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { + assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); + + unsigned NumOperands = MI->getNumOperands(); + + // Count the number of register definitions to find the asm string. + unsigned NumDefs = 0; + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) + assert(NumDefs != NumOperands-1 && "No asm string?"); + + assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); + + // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. + const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + + // If this asmstr is empty, just print the #APP/#NOAPP markers. + // These are useful to see where empty asm's wound up. + if (AsmStr[0] == 0) { + // Don't emit the comments if writing to a .o file. + if (!OutStreamer.hasRawTextSupport()) return; + + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); + return; + } + + // Emit the #APP start marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + + // Emit the inline asm to a temporary string so we can emit it through + // EmitInlineAsm. + SmallString<256> StringData; + raw_svector_ostream OS(StringData); + + OS << '\t'; + + // The variant of the current asmprinter. + int AsmPrinterVariant = MAI->getAssemblerDialect(); + + int CurVariant = -1; // The number of the {.|.|.} region we are in. + const char *LastEmitted = AsmStr; // One past the last character emitted. + + while (*LastEmitted) { + switch (*LastEmitted) { + default: { + // Not a special case, emit the string section literally. + const char *LiteralEnd = LastEmitted+1; + while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && + *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') + ++LiteralEnd; + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + OS.write(LastEmitted, LiteralEnd-LastEmitted); + LastEmitted = LiteralEnd; + break; + } + case '\n': + ++LastEmitted; // Consume newline character. + OS << '\n'; // Indent code with newline. + break; + case '$': { + ++LastEmitted; // Consume '$' character. + bool Done = true; + + // Handle escapes. + switch (*LastEmitted) { + default: Done = false; break; + case '$': // $$ -> $ + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + OS << '$'; + ++LastEmitted; // Consume second '$' character. + break; + case '(': // $( -> same as GCC's { character. + ++LastEmitted; // Consume '(' character. + if (CurVariant != -1) { + llvm_report_error("Nested variants found in inline asm string: '" + + std::string(AsmStr) + "'"); + } + CurVariant = 0; // We're in the first variant now. + break; + case '|': + ++LastEmitted; // consume '|' character. + if (CurVariant == -1) + OS << '|'; // this is gcc's behavior for | outside a variant + else + ++CurVariant; // We're in the next variant. + break; + case ')': // $) -> same as GCC's } char. + ++LastEmitted; // consume ')' character. + if (CurVariant == -1) + OS << '}'; // this is gcc's behavior for } outside a variant + else + CurVariant = -1; + break; + } + if (Done) break; + + bool HasCurlyBraces = false; + if (*LastEmitted == '{') { // ${variable} + ++LastEmitted; // Consume '{' character. + HasCurlyBraces = true; + } + + // If we have ${:foo}, then this is not a real operand reference, it is a + // "magic" string reference, just like in .td files. Arrange to call + // PrintSpecial. + if (HasCurlyBraces && *LastEmitted == ':') { + ++LastEmitted; + const char *StrStart = LastEmitted; + const char *StrEnd = strchr(StrStart, '}'); + if (StrEnd == 0) + llvm_report_error(Twine("Unterminated ${:foo} operand in inline asm" + " string: '") + Twine(AsmStr) + "'"); + + std::string Val(StrStart, StrEnd); + PrintSpecial(MI, OS, Val.c_str()); + LastEmitted = StrEnd+1; + break; + } + + const char *IDStart = LastEmitted; + const char *IDEnd = IDStart; + while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; + + unsigned Val; + if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) + llvm_report_error("Bad $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); + LastEmitted = IDEnd; + + char Modifier[2] = { 0, 0 }; + + if (HasCurlyBraces) { + // If we have curly braces, check for a modifier character. This + // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. + if (*LastEmitted == ':') { + ++LastEmitted; // Consume ':' character. + if (*LastEmitted == 0) + llvm_report_error("Bad ${:} expression in inline asm string: '" + + std::string(AsmStr) + "'"); + + Modifier[0] = *LastEmitted; + ++LastEmitted; // Consume modifier character. + } + + if (*LastEmitted != '}') + llvm_report_error("Bad ${} expression in inline asm string: '" + + std::string(AsmStr) + "'"); + ++LastEmitted; // Consume '}' character. + } + + if (Val >= NumOperands-1) + llvm_report_error("Invalid $ operand number in inline asm string: '" + + std::string(AsmStr) + "'"); + + // Okay, we finally have a value number. Ask the target to print this + // operand! + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { + unsigned OpNo = 1; + + bool Error = false; + + // Scan to find the machine operand number for the operand. + for (; Val; --Val) { + if (OpNo >= MI->getNumOperands()) break; + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; + } + + if (OpNo >= MI->getNumOperands()) { + Error = true; + } else { + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + ++OpNo; // Skip over the ID number. + + if (Modifier[0] == 'l') // labels are target independent + // FIXME: What if the operand isn't an MBB, report error? + OS << *MI->getOperand(OpNo).getMBB()->getSymbol(); + else { + AsmPrinter *AP = const_cast<AsmPrinter*>(this); + if ((OpFlags & 7) == 4) { + Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0, + OS); + } else { + Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0, OS); + } + } + } + if (Error) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n"; + MI->print(Msg); + llvm_report_error(Msg.str()); + } + } + break; + } + } + } + OS << '\n' << (char)0; // null terminate string. + EmitInlineAsm(OS.str(), 0/*no loc cookie*/); + + // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); +} + + +/// 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, raw_ostream &OS, + const char *Code) const { + if (!strcmp(Code, "private")) { + OS << MAI->getPrivateGlobalPrefix(); + } else if (!strcmp(Code, "comment")) { + OS << MAI->getCommentString(); + } else if (!strcmp(Code, "uid")) { + // Comparing the address of MI isn't sufficient, because machineinstrs may + // be allocated to the same address across functions. + + // If this is a new LastFn instruction, bump the counter. + if (LastMI != MI || LastFn != getFunctionNumber()) { + ++Counter; + LastMI = MI; + LastFn = getFunctionNumber(); + } + OS << Counter; + } else { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Unknown special formatter '" << Code + << "' for machine instr: " << *MI; + llvm_report_error(Msg.str()); + } +} + +/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM +/// instruction, using the specified assembler variant. Targets should +/// override this to format as appropriate. +bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { + // Target doesn't support this yet! + return true; +} + +bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + // Target doesn't support this yet! + return true; +} + diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index 7dc1fb596568..afc482dd15bf 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -1,9 +1,9 @@ add_llvm_library(LLVMAsmPrinter AsmPrinter.cpp + AsmPrinterDwarf.cpp + AsmPrinterInlineAsm.cpp DIE.cpp DwarfDebug.cpp DwarfException.cpp - DwarfPrinter.cpp - DwarfWriter.cpp OcamlGCPrinter.cpp ) diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index e0e3ff794672..b2c70d51f5a5 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "DIE.h" -#include "DwarfPrinter.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/MC/MCAsmInfo.h" @@ -54,14 +53,14 @@ void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { /// Emit - Print the abbreviation using the specified asm printer. /// -void DIEAbbrev::Emit(const DwarfPrinter *DP) const { +void DIEAbbrev::Emit(AsmPrinter *AP) const { // Emit its Dwarf tag type. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(Tag, dwarf::TagString(Tag)); + AP->EmitULEB128(Tag, dwarf::TagString(Tag)); // Emit whether it has children DIEs. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); + AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); // For each attribute description. for (unsigned i = 0, N = Data.size(); i < N; ++i) { @@ -69,18 +68,18 @@ void DIEAbbrev::Emit(const DwarfPrinter *DP) const { // Emit attribute type. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(AttrData.getAttribute(), - dwarf::AttributeString(AttrData.getAttribute())); + AP->EmitULEB128(AttrData.getAttribute(), + dwarf::AttributeString(AttrData.getAttribute())); // Emit form type. // FIXME: Doing work even in non-asm-verbose runs. - DP->EmitULEB128(AttrData.getForm(), + AP->EmitULEB128(AttrData.getForm(), dwarf::FormEncodingString(AttrData.getForm())); } // Mark end of abbreviation. - DP->EmitULEB128(0, "EOM(1)"); - DP->EmitULEB128(0, "EOM(2)"); + AP->EmitULEB128(0, "EOM(1)"); + AP->EmitULEB128(0, "EOM(2)"); } #ifndef NDEBUG @@ -188,8 +187,7 @@ void DIEValue::dump() { /// EmitValue - Emit integer of appropriate size. /// -void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { - const AsmPrinter *Asm = D->getAsm(); +void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const { unsigned Size = ~0U; switch (Form) { case dwarf::DW_FORM_flag: // Fall thru @@ -201,8 +199,8 @@ void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { case dwarf::DW_FORM_data4: Size = 4; break; case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_data8: Size = 8; break; - case dwarf::DW_FORM_udata: D->EmitULEB128(Integer); return; - case dwarf::DW_FORM_sdata: D->EmitSLEB128(Integer, ""); return; + case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return; + case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; default: llvm_unreachable("DIE Value form not supported yet"); } Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/); @@ -210,7 +208,7 @@ void DIEInteger::EmitValue(DwarfPrinter *D, unsigned Form) const { /// SizeOf - Determine size of integer value in bytes. /// -unsigned DIEInteger::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const { switch (Form) { case dwarf::DW_FORM_flag: // Fall thru case dwarf::DW_FORM_ref1: // Fall thru @@ -241,10 +239,10 @@ void DIEInteger::print(raw_ostream &O) { /// EmitValue - Emit string value. /// -void DIEString::EmitValue(DwarfPrinter *D, unsigned Form) const { - D->getAsm()->OutStreamer.EmitBytes(Str, /*addrspace*/0); +void DIEString::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->OutStreamer.EmitBytes(Str, /*addrspace*/0); // Emit nul terminator. - D->getAsm()->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); + AP->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); } #ifndef NDEBUG @@ -259,17 +257,15 @@ void DIEString::print(raw_ostream &O) { /// EmitValue - Emit label value. /// -void DIELabel::EmitValue(DwarfPrinter *D, unsigned Form) const { - bool IsSmall = Form == dwarf::DW_FORM_data4; - unsigned Size = IsSmall ? 4 : D->getTargetData()->getPointerSize(); - D->getAsm()->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/); +void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->OutStreamer.EmitSymbolValue(Label, SizeOf(AP, Form), 0/*AddrSpace*/); } /// SizeOf - Determine size of label value in bytes. /// -unsigned DIELabel::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; - return TD->getPointerSize(); + return AP->getTargetData().getPointerSize(); } #ifndef NDEBUG @@ -284,16 +280,15 @@ void DIELabel::print(raw_ostream &O) { /// EmitValue - Emit delta value. /// -void DIEDelta::EmitValue(DwarfPrinter *D, unsigned Form) const { - bool IsSmall = Form == dwarf::DW_FORM_data4; - D->EmitDifference(LabelHi, LabelLo, IsSmall); +void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form)); } /// SizeOf - Determine size of delta value in bytes. /// -unsigned DIEDelta::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const { if (Form == dwarf::DW_FORM_data4) return 4; - return TD->getPointerSize(); + return AP->getTargetData().getPointerSize(); } #ifndef NDEBUG @@ -308,8 +303,8 @@ void DIEDelta::print(raw_ostream &O) { /// EmitValue - Emit debug information entry offset. /// -void DIEEntry::EmitValue(DwarfPrinter *D, unsigned Form) const { - D->getAsm()->EmitInt32(Entry->getOffset()); +void DIEEntry::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->EmitInt32(Entry->getOffset()); } #ifndef NDEBUG @@ -324,11 +319,11 @@ void DIEEntry::print(raw_ostream &O) { /// ComputeSize - calculate the size of the block. /// -unsigned DIEBlock::ComputeSize(const TargetData *TD) { +unsigned DIEBlock::ComputeSize(AsmPrinter *AP) { if (!Size) { const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); for (unsigned i = 0, N = Values.size(); i < N; ++i) - Size += Values[i]->SizeOf(TD, AbbrevData[i].getForm()); + Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm()); } return Size; @@ -336,29 +331,28 @@ unsigned DIEBlock::ComputeSize(const TargetData *TD) { /// EmitValue - Emit block data. /// -void DIEBlock::EmitValue(DwarfPrinter *D, unsigned Form) const { - const AsmPrinter *Asm = D->getAsm(); +void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const { switch (Form) { - case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; - case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; - case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; - case dwarf::DW_FORM_block: D->EmitULEB128(Size); break; - default: llvm_unreachable("Improper form for block"); break; + default: assert(0 && "Improper form for block"); break; + case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; + case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break; } const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData(); for (unsigned i = 0, N = Values.size(); i < N; ++i) - Values[i]->EmitValue(D, AbbrevData[i].getForm()); + Values[i]->EmitValue(Asm, AbbrevData[i].getForm()); } /// SizeOf - Determine size of block data in bytes. /// -unsigned DIEBlock::SizeOf(const TargetData *TD, unsigned Form) const { +unsigned DIEBlock::SizeOf(AsmPrinter *AP, unsigned Form) const { switch (Form) { case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); - case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); + case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); default: llvm_unreachable("Improper form for block"); break; } return 0; diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index 8b27ed20cb63..454326db0ea1 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -22,8 +22,6 @@ namespace llvm { class AsmPrinter; - class DwarfPrinter; - class TargetData; class MCSymbol; class raw_ostream; @@ -101,7 +99,7 @@ namespace llvm { /// Emit - Print the abbreviation using the specified asm printer. /// - void Emit(const DwarfPrinter *DP) const; + void Emit(AsmPrinter *AP) const; #ifndef NDEBUG void print(raw_ostream &O); @@ -221,11 +219,11 @@ namespace llvm { /// EmitValue - Emit value via the Dwarf writer. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const = 0; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const = 0; /// SizeOf - Return the size of a value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const = 0; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const = 0; // Implement isa/cast/dyncast. static bool classof(const DIEValue *) { return true; } @@ -261,11 +259,11 @@ namespace llvm { /// EmitValue - Emit integer of appropriate size. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of integer value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. @@ -287,11 +285,11 @@ namespace llvm { /// EmitValue - Emit string value. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of string value in bytes. /// - virtual unsigned SizeOf(const TargetData *, unsigned /*Form*/) const { + virtual unsigned SizeOf(AsmPrinter *AP, unsigned /*Form*/) const { return Str.size() + sizeof(char); // sizeof('\0'); } @@ -314,11 +312,11 @@ namespace llvm { /// EmitValue - Emit label value. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of label value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. static bool classof(const DIELabel *) { return true; } @@ -341,11 +339,11 @@ namespace llvm { /// EmitValue - Emit delta value. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of delta value in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. static bool classof(const DIEDelta *) { return true; } @@ -369,11 +367,11 @@ namespace llvm { /// EmitValue - Emit debug information entry offset. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of debug information entry in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const { + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const { return sizeof(int32_t); } @@ -398,7 +396,7 @@ namespace llvm { /// ComputeSize - calculate the size of the block. /// - unsigned ComputeSize(const TargetData *TD); + unsigned ComputeSize(AsmPrinter *AP); /// BestForm - Choose the best form for data. /// @@ -411,11 +409,11 @@ namespace llvm { /// EmitValue - Emit block data. /// - virtual void EmitValue(DwarfPrinter *D, unsigned Form) const; + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; /// SizeOf - Determine size of block data in bytes. /// - virtual unsigned SizeOf(const TargetData *TD, unsigned Form) const; + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; // Implement isa/cast/dyncast. static bool classof(const DIEBlock *) { return true; } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 9084456c8f4d..b472d1e5335c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -13,6 +13,8 @@ #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" +#include "DIE.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -24,7 +26,9 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" @@ -269,6 +273,8 @@ public: void dump() const; #endif }; + +} // end llvm namespace #ifndef NDEBUG void DbgScope::dump() const { @@ -296,16 +302,19 @@ DbgScope::~DbgScope() { delete Variables[j]; } -} // end llvm namespace - -DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) - : DwarfPrinter(OS, A, T), ModuleCU(0), - AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), - DIEBlocks(), SectionSourceLines(), didInitial(false), shouldEmit(false), +DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) + : Asm(A), MMI(Asm->MMI), ModuleCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), CurrentFnDbgScope(0), DebugTimer(0) { NextStringPoolNumber = 0; + + DwarfFrameSectionSym = DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; + DwarfStrSectionSym = TextSectionSym = 0; + if (TimePassesIsEnabled) DebugTimer = new Timer("Dwarf Debug Writer"); + + beginModule(M); } DwarfDebug::~DwarfDebug() { for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) @@ -319,7 +328,7 @@ MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) { if (Entry.first) return Entry.first; Entry.second = NextStringPoolNumber++; - return Entry.first = getDWLabel("string", Entry.second); + return Entry.first = Asm->GetTempSymbol("string", Entry.second); } @@ -395,11 +404,19 @@ void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, Die->addValue(Attribute, Form, Value); } +/// addDIEEntry - Add a DIE attribute data and value. +/// +void DwarfDebug::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, + DIE *Entry) { + Die->addValue(Attribute, Form, createDIEEntry(Entry)); +} + + /// addBlock - Add block data. /// void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block) { - Block->ComputeSize(TD); + Block->ComputeSize(Asm); DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. Die->addValue(Attribute, Block->BestForm(), Block); } @@ -553,6 +570,7 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, // Decode the original location, and use that as the start of the byref // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); @@ -693,6 +711,7 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, // Decode the original location, and use that as the start of the byref // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); @@ -748,6 +767,7 @@ void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, /// provided. void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, const MachineLocation &Location) { + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); @@ -1114,7 +1134,8 @@ DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) { Offset -= FieldOffset; // Maybe we need to work from the other end. - if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); + if (Asm->getTargetData().isLittleEndian()) + Offset = FieldSize - (Offset + Size); addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); // Here WD_AT_data_member_location points to the anonymous @@ -1272,7 +1293,7 @@ DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, if (!Parent && !InlinedAt) { StringRef SPName = DISubprogram(N).getLinkageName(); - if (SPName == MF->getFunction()->getName()) + if (SPName == Asm->MF->getFunction()->getName()) CurrentFnDbgScope = NScope; } @@ -1316,50 +1337,51 @@ DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) { /// If there are global variables in this scope then create and insert /// DIEs for these variables. DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { - DIE *SPDie = ModuleCU->getDIE(SPNode); - assert(SPDie && "Unable to find subprogram DIE!"); - DISubprogram SP(SPNode); + DIE *SPDie = ModuleCU->getDIE(SPNode); + assert(SPDie && "Unable to find subprogram DIE!"); + DISubprogram SP(SPNode); + + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() && + !SP.getContext().isFile() && !SP.getContext().isSubprogram()) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(DIType(Args.getElement(i).getNode())); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPDie->addChild(Arg); + } + DIE *SPDeclDie = SPDie; + SPDie = new DIE(dwarf::DW_TAG_subprogram); + addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + SPDeclDie); + ModuleCU->addDie(SPDie); + } + + addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); + addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + MachineLocation Location(RI->getFrameRegister(*Asm->MF)); + addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + + if (!DISubprogram(SPNode).isLocalToUnit()) + addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - // There is not any need to generate specification DIE for a function - // defined at compile unit level. If a function is defined inside another - // function then gdb prefers the definition at top level and but does not - // expect specification DIE in parent function. So avoid creating - // specification DIE for a function defined inside a function. - if (SP.isDefinition() && !SP.getContext().isCompileUnit() && - !SP.getContext().isFile() && !SP.getContext().isSubprogram()) { - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(DIType(Args.getElement(i).getNode())); - addType(Arg, ATy); - if (ATy.isArtificial()) - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); - SPDie->addChild(Arg); - } - DIE *SPDeclDie = SPDie; - SPDie = new DIE(dwarf::DW_TAG_subprogram); - addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, - SPDeclDie); - ModuleCU->addDie(SPDie); - } - - addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - getDWLabel("func_begin", SubprogramCount)); - addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - getDWLabel("func_end", SubprogramCount)); - MachineLocation Location(RI->getFrameRegister(*MF)); - addAddress(SPDie, dwarf::DW_AT_frame_base, Location); - - if (!DISubprogram(SPNode).isLocalToUnit()) - addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - - return SPDie; + return SPDie; } /// constructLexicalScope - Construct new DW_TAG_lexical_block @@ -1377,9 +1399,10 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { return ScopeDIE; addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - Start ? Start : getDWLabel("func_begin", SubprogramCount)); + Start ? Start : Asm->GetTempSymbol("func_begin", + Asm->getFunctionNumber())); addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - End ? End : getDWLabel("func_end", SubprogramCount)); + End ? End : Asm->GetTempSymbol("func_end",Asm->getFunctionNumber())); return ScopeDIE; } @@ -1510,6 +1533,31 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { if (MCSymbol *VS = DV->getDbgValueLabel()) addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr, VS); + } else if (DbgValueInsn->getOperand(0).getType() == + MachineOperand::MO_FPImmediate) { + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + APFloat FPImm = DbgValueInsn->getOperand(0).getFPImm()->getValueAPF(); + + // Get the raw data form of the floating point. + const APInt FltVal = FPImm.bitcastToAPInt(); + const char *FltPtr = (const char*)FltVal.getRawData(); + + unsigned NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & FltPtr[Start]); + + addBlock(VariableDie, dwarf::DW_AT_const_value, 0, Block); + + if (MCSymbol *VS = DV->getDbgValueLabel()) + addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr, + VS); } else { //FIXME : Handle other operand types. delete VariableDie; @@ -1519,7 +1567,8 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { } else { MachineLocation Location; unsigned FrameReg; - int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + int Offset = RI->getFrameIndexReference(*Asm->MF, DV->getFrameIndex(), FrameReg); Location.set(FrameReg, Offset); @@ -1667,10 +1716,9 @@ void DwarfDebug::constructCompileUnit(MDNode *N) { addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1, DIUnit.getLanguage()); addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); - addLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - getTempLabel("text_begin")); + addLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, TextSectionSym); addLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - getTempLabel("text_end")); + Asm->GetTempSymbol("text_end")); // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. It is always zero when only one // compile unit is emitted in one object file. @@ -1780,25 +1828,37 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) { /// beginModule - Emit all Dwarf sections that should come prior to the /// content. Create global DIEs and emit initial debug info sections. /// This is inovked by the target AsmPrinter. -void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { - this->M = M; - - if (!MAI->doesSupportDebugInformation()) - return; - +void DwarfDebug::beginModule(Module *M) { TimeRegion Timer(DebugTimer); - + DebugInfoFinder DbgFinder; DbgFinder.processModule(*M); + bool HasDebugInfo = false; + + // Scan all the compile-units to see if there are any marked as the main unit. + // if not, we do not generate debug info. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) { + if (DICompileUnit(*I).isMain()) { + HasDebugInfo = true; + break; + } + } + + if (!HasDebugInfo) return; + + // Tell MMI that we have debug info. + MMI->setDebugInfoAvailability(true); + + // Emit initial sections. + EmitSectionLabels(); + // Create all the compile unit DIEs. for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), E = DbgFinder.compile_unit_end(); I != E; ++I) constructCompileUnit(*I); - if (!ModuleCU) - return; - // Create DIEs for each subprogram. for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), E = DbgFinder.subprogram_end(); I != E; ++I) @@ -1809,16 +1869,12 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { E = DbgFinder.global_variable_end(); I != E; ++I) constructGlobalVariableDIE(*I); - MMI = mmi; - shouldEmit = true; - MMI->setDebugInfoAvailability(true); - // Prime section data. SectionMap.insert(Asm->getObjFileLowering().getTextSection()); // Print out .file directives to specify files for .loc directives. These are // printed out early so that they precede any .loc directives. - if (MAI->hasDotLocAndDotFile()) { + if (Asm->MAI->hasDotLocAndDotFile()) { for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i); @@ -1832,9 +1888,6 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { Asm->OutStreamer.EmitDwarfFileDirective(i, FullPath.str()); } } - - // Emit initial sections - emitInitial(); } /// endModule - Emit all Dwarf sections that should come after the content. @@ -1871,14 +1924,14 @@ void DwarfDebug::endModule() { // Standard sections final addresses. Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("text_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end")); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("data_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end")); // End text sections. for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) { Asm->OutStreamer.SwitchSection(SectionMap[i]); - Asm->OutStreamer.EmitLabel(getDWLabel("section_end", i)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", i)); } // Emit common frame information. @@ -1975,9 +2028,7 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, /// collectVariableInfo - Populate DbgScope entries with variables' info. void DwarfDebug::collectVariableInfo() { - if (!MMI) return; - - const LLVMContext &Ctx = MF->getFunction()->getContext(); + const LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), @@ -2003,7 +2054,7 @@ void DwarfDebug::collectVariableInfo() { } // Collect variable information from DBG_VALUE machine instructions; - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -2055,7 +2106,7 @@ void DwarfDebug::beginScope(const MachineInstr *MI) { if (DL == PrevInstLoc) return; - MDNode *Scope = DL.getScope(MF->getFunction()->getContext()); + MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); // FIXME: Should only verify each scope once! if (!DIScope(Scope).Verify()) @@ -2148,10 +2199,10 @@ bool DwarfDebug::extractScopeInformation() { DenseMap<const MachineInstr *, unsigned> MIIndexMap; unsigned MIIndex = 0; - LLVMContext &Ctx = MF->getFunction()->getContext(); + LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); // Scan each instruction and create scopes. First build working set of scopes. - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -2175,7 +2226,7 @@ bool DwarfDebug::extractScopeInformation() { // Build scope hierarchy using working set of scopes. - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -2243,18 +2294,17 @@ bool DwarfDebug::extractScopeInformation() { /// beginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. void DwarfDebug::beginFunction(const MachineFunction *MF) { - this->MF = MF; - - if (!ShouldEmitDwarfDebug()) return; + if (!MMI->hasDebugInfo()) return; + + TimeRegion Timer(DebugTimer); if (!extractScopeInformation()) return; - TimeRegion Timer(DebugTimer); - collectVariableInfo(); // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_begin", + Asm->getFunctionNumber())); // Emit label for the implicitly defined dbg.stoppoint at the start of the // function. @@ -2279,14 +2329,15 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { /// endFunction - Gather and emit post-function debug information. /// void DwarfDebug::endFunction(const MachineFunction *MF) { - if (!ShouldEmitDwarfDebug()) return; - if (DbgScopeMap.empty()) return; + if (!MMI->hasDebugInfo() || + DbgScopeMap.empty()) return; TimeRegion Timer(DebugTimer); if (CurrentFnDbgScope) { // Define end label for subprogram. - Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_end", + Asm->getFunctionNumber())); // Get function line info. if (!Lines.empty()) { @@ -2306,7 +2357,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { constructScopeDIE(CurrentFnDbgScope); - DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount, + DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), MMI->getFrameMoves())); } @@ -2327,9 +2378,6 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { /// unique label that was emitted and which provides correspondence to /// the source line list. MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) { - if (!MMI) - return 0; - TimeRegion Timer(DebugTimer); StringRef Dir; @@ -2404,7 +2452,7 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { // Size the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) // Size attribute value. - Offset += Values[i]->SizeOf(TD, AbbrevData[i].getForm()); + Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); // Size the DIE children if any. if (!Children.empty()) { @@ -2436,50 +2484,48 @@ void DwarfDebug::computeSizeAndOffsets() { CompileUnitOffsets[ModuleCU] = 0; } -/// emitInitial - Emit initial Dwarf declarations. This is necessary for cc -/// tools to recognize the object file contains Dwarf information. -void DwarfDebug::emitInitial() { - // Check to see if we already emitted intial headers. - if (didInitial) return; - didInitial = true; +/// EmitSectionSym - Switch to the specified MCSection and emit an assembler +/// temporary label to it if SymbolStem is specified. +static MCSymbol *EmitSectionSym(AsmPrinter *Asm, const MCSection *Section, + const char *SymbolStem = 0) { + Asm->OutStreamer.SwitchSection(Section); + if (!SymbolStem) return 0; + + MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); + Asm->OutStreamer.EmitLabel(TmpSym); + return TmpSym; +} +/// EmitSectionLabels - Emit initial Dwarf sections with a label at +/// the start of each one. +void DwarfDebug::EmitSectionLabels() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); // Dwarf sections base addresses. - if (MAI->doesDwarfRequireFrameSection()) { - Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame")); - } - - Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_info")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges")); - - if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) { - Asm->OutStreamer.SwitchSection(LineInfoDirective); - Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo")); - } - - Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_line")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_loc")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_str")); - Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges")); - - Asm->OutStreamer.SwitchSection(TLOF.getTextSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("text_begin")); - Asm->OutStreamer.SwitchSection(TLOF.getDataSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("data_begin")); + if (Asm->MAI->doesDwarfRequireFrameSection()) { + DwarfFrameSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfFrameSection(), "section_debug_frame"); + } + + DwarfInfoSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + DwarfAbbrevSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); + EmitSectionSym(Asm, TLOF.getDwarfARangesSection()); + + if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) + EmitSectionSym(Asm, MacroInfo); + + EmitSectionSym(Asm, TLOF.getDwarfLineSection()); + EmitSectionSym(Asm, TLOF.getDwarfLocSection()); + EmitSectionSym(Asm, TLOF.getDwarfPubNamesSection()); + EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); + DwarfStrSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str"); + EmitSectionSym(Asm, TLOF.getDwarfRangesSection()); + + TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); + EmitSectionSym(Asm, TLOF.getDataSection()); } /// emitDIE - Recusively Emits a debug information entry. @@ -2490,12 +2536,12 @@ void DwarfDebug::emitDIE(DIE *Die) { const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; // Emit the code (index) for the abbreviation. - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + Twine::utohexstr(Die->getOffset()) + ":0x" + Twine::utohexstr(Die->getSize()) + " " + dwarf::TagString(Abbrev->getTag())); - EmitULEB128(AbbrevNumber); + Asm->EmitULEB128(AbbrevNumber); const SmallVector<DIEValue*, 32> &Values = Die->getValues(); const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData(); @@ -2506,7 +2552,7 @@ void DwarfDebug::emitDIE(DIE *Die) { unsigned Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); switch (Attr) { @@ -2522,7 +2568,7 @@ void DwarfDebug::emitDIE(DIE *Die) { } default: // Emit an attribute using the defined form. - Values[i]->EmitValue(this, Form); + Values[i]->EmitValue(Asm, Form); break; } } @@ -2534,7 +2580,7 @@ void DwarfDebug::emitDIE(DIE *Die) { for (unsigned j = 0, M = Children.size(); j < M; ++j) emitDIE(Children[j]); - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("End Of Children Mark"); Asm->EmitInt8(0); } @@ -2549,7 +2595,8 @@ void DwarfDebug::emitDebugInfo() { DIE *Die = ModuleCU->getCUDie(); // Emit the compile units header. - Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_begin", + ModuleCU->getID())); // Emit size of content not including length itself unsigned ContentSize = Die->getSize() + @@ -2563,10 +2610,10 @@ void DwarfDebug::emitDebugInfo() { Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); - EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"), - true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"), + DwarfAbbrevSectionSym); Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(TD->getPointerSize()); + Asm->EmitInt8(Asm->getTargetData().getPointerSize()); emitDIE(Die); // FIXME - extra padding for gdb bug. @@ -2575,7 +2622,7 @@ void DwarfDebug::emitDebugInfo() { Asm->EmitInt8(0); Asm->EmitInt8(0); Asm->EmitInt8(0); - Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", ModuleCU->getID())); } /// emitAbbreviations - Emit the abbreviation section. @@ -2587,7 +2634,7 @@ void DwarfDebug::emitAbbreviations() const { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAbbrevSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_begin")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_begin")); // For each abbrevation. for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) { @@ -2595,16 +2642,16 @@ void DwarfDebug::emitAbbreviations() const { const DIEAbbrev *Abbrev = Abbreviations[i]; // Emit the abbrevations code (base 1 index.) - EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); + Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); // Emit the abbreviations data. - Abbrev->Emit(this); + Abbrev->Emit(Asm); } // Mark end of abbreviations. - EmitULEB128(0, "EOM(3)"); + Asm->EmitULEB128(0, "EOM(3)"); - Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_end")); } } @@ -2617,14 +2664,15 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->EmitInt8(0); Asm->OutStreamer.AddComment("Op size"); - Asm->EmitInt8(TD->getPointerSize() + 1); + Asm->EmitInt8(Asm->getTargetData().getPointerSize() + 1); Asm->OutStreamer.AddComment("DW_LNE_set_address"); Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->OutStreamer.AddComment("Section end label"); - Asm->OutStreamer.EmitSymbolValue(getDWLabel("section_end", SectionEnd), - TD->getPointerSize(), 0/*AddrSpace*/); + Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), + Asm->getTargetData().getPointerSize(), + 0/*AddrSpace*/); // Mark end of matrix. Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); @@ -2638,7 +2686,7 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { void DwarfDebug::emitDebugLines() { // If the target is using .loc/.file, the assembler will be emitting the // .debug_line table automatically. - if (MAI->hasDotLocAndDotFile()) + if (Asm->MAI->hasDotLocAndDotFile()) return; // Minimum line delta, thus ranging from -10..(255-10). @@ -2652,16 +2700,17 @@ void DwarfDebug::emitDebugLines() { // Construct the section header. Asm->OutStreamer.AddComment("Length of Source Line Info"); - EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true); - Asm->OutStreamer.EmitLabel(getTempLabel("line_begin")); + Asm->EmitLabelDifference(Asm->GetTempSymbol("line_end"), + Asm->GetTempSymbol("line_begin"), 4); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_begin")); Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Prolog Length"); - EmitDifference(getTempLabel("line_prolog_end"), - getTempLabel("line_prolog_begin"), true); - Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin")); + Asm->EmitLabelDifference(Asm->GetTempSymbol("line_prolog_end"), + Asm->GetTempSymbol("line_prolog_begin"), 4); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_prolog_begin")); Asm->OutStreamer.AddComment("Minimum Instruction Length"); Asm->EmitInt8(1); @@ -2697,7 +2746,7 @@ void DwarfDebug::emitDebugLines() { // Emit directories. for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { const std::string &Dir = getSourceDirectoryName(DI); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Directory"); Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0); } @@ -2709,18 +2758,18 @@ void DwarfDebug::emitDebugLines() { // Remember source id starts at 1. std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI); const std::string &FN = getSourceFileName(Id.second); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Source"); Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0); - EmitULEB128(Id.first, "Directory #"); - EmitULEB128(0, "Mod date"); - EmitULEB128(0, "File size"); + Asm->EmitULEB128(Id.first, "Directory #"); + Asm->EmitULEB128(0, "Mod date"); + Asm->EmitULEB128(0, "File size"); } Asm->OutStreamer.AddComment("End of files"); Asm->EmitInt8(0); - Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_prolog_end")); // A sequence for each text section. unsigned SecSrcLinesSize = SectionSourceLines.size(); @@ -2754,13 +2803,14 @@ void DwarfDebug::emitDebugLines() { Asm->OutStreamer.AddComment("Extended Op"); Asm->EmitInt8(0); Asm->OutStreamer.AddComment("Op size"); - Asm->EmitInt8(TD->getPointerSize() + 1); + Asm->EmitInt8(Asm->getTargetData().getPointerSize() + 1); Asm->OutStreamer.AddComment("DW_LNE_set_address"); Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->OutStreamer.AddComment("Location label"); - Asm->OutStreamer.EmitSymbolValue(Label, TD->getPointerSize(), + Asm->OutStreamer.EmitSymbolValue(Label, + Asm->getTargetData().getPointerSize(), 0/*AddrSpace*/); // If change of source, then switch to the new source. @@ -2768,7 +2818,7 @@ void DwarfDebug::emitDebugLines() { Source = LineInfo.getSourceID(); Asm->OutStreamer.AddComment("DW_LNS_set_file"); Asm->EmitInt8(dwarf::DW_LNS_set_file); - EmitULEB128(Source, "New Source"); + Asm->EmitULEB128(Source, "New Source"); } // If change of line. @@ -2789,7 +2839,7 @@ void DwarfDebug::emitDebugLines() { // ... otherwise use long hand. Asm->OutStreamer.AddComment("DW_LNS_advance_line"); Asm->EmitInt8(dwarf::DW_LNS_advance_line); - EmitSLEB128(Offset, "Line Offset"); + Asm->EmitSLEB128(Offset, "Line Offset"); Asm->OutStreamer.AddComment("DW_LNS_copy"); Asm->EmitInt8(dwarf::DW_LNS_copy); } @@ -2809,55 +2859,56 @@ void DwarfDebug::emitDebugLines() { // put into it, emit an empty table. emitEndOfLineMatrix(1); - Asm->OutStreamer.EmitLabel(getTempLabel("line_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_end")); } /// emitCommonDebugFrame - Emit common frame info into a debug frame section. /// void DwarfDebug::emitCommonDebugFrame() { - if (!MAI->doesDwarfRequireFrameSection()) + if (!Asm->MAI->doesDwarfRequireFrameSection()) return; - int stackGrowth = - Asm->TM.getFrameInfo()->getStackGrowthDirection() == - TargetFrameInfo::StackGrowsUp ? - TD->getPointerSize() : -TD->getPointerSize(); + int stackGrowth = Asm->getTargetData().getPointerSize(); + if (Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsDown) + stackGrowth *= -1; // Start the dwarf frame section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfFrameSection()); - Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common")); Asm->OutStreamer.AddComment("Length of Common Information Entry"); - EmitDifference(getTempLabel("debug_frame_common_end"), - getTempLabel("debug_frame_common_begin"), true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_frame_common_end"), + Asm->GetTempSymbol("debug_frame_common_begin"), 4); - Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_begin")); Asm->OutStreamer.AddComment("CIE Identifier Tag"); Asm->EmitInt32((int)dwarf::DW_CIE_ID); Asm->OutStreamer.AddComment("CIE Version"); Asm->EmitInt8(dwarf::DW_CIE_VERSION); Asm->OutStreamer.AddComment("CIE Augmentation"); Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator. - EmitULEB128(1, "CIE Code Alignment Factor"); - EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->EmitULEB128(1, "CIE Code Alignment Factor"); + Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); Asm->OutStreamer.AddComment("CIE RA Column"); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); std::vector<MachineMove> Moves; RI->getInitialFrameState(Moves); - EmitFrameMoves(0, Moves, false); + Asm->EmitFrameMoves(Moves, 0, false); Asm->EmitAlignment(2, 0, 0, false); - Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end")); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_end")); } /// emitFunctionDebugFrame - Emit per function frame info into a debug frame /// section. void DwarfDebug:: emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) { - if (!MAI->doesDwarfRequireFrameSection()) + if (!Asm->MAI->doesDwarfRequireFrameSection()) return; // Start the dwarf frame section. @@ -2866,27 +2917,30 @@ emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) { Asm->OutStreamer.AddComment("Length of Frame Information Entry"); MCSymbol *DebugFrameBegin = - getDWLabel("debug_frame_begin", DebugFrameInfo.Number); + Asm->GetTempSymbol("debug_frame_begin", DebugFrameInfo.Number); MCSymbol *DebugFrameEnd = - getDWLabel("debug_frame_end", DebugFrameInfo.Number); - EmitDifference(DebugFrameEnd, DebugFrameBegin, true); + Asm->GetTempSymbol("debug_frame_end", DebugFrameInfo.Number); + Asm->EmitLabelDifference(DebugFrameEnd, DebugFrameBegin, 4); Asm->OutStreamer.EmitLabel(DebugFrameBegin); Asm->OutStreamer.AddComment("FDE CIE offset"); - EmitSectionOffset(getTempLabel("debug_frame_common"), - getTempLabel("section_debug_frame"), true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("debug_frame_common"), + DwarfFrameSectionSym); Asm->OutStreamer.AddComment("FDE initial location"); - MCSymbol *FuncBeginSym = getDWLabel("func_begin", DebugFrameInfo.Number); + MCSymbol *FuncBeginSym = + Asm->GetTempSymbol("func_begin", DebugFrameInfo.Number); Asm->OutStreamer.EmitSymbolValue(FuncBeginSym, - TD->getPointerSize(), 0/*AddrSpace*/); + Asm->getTargetData().getPointerSize(), + 0/*AddrSpace*/); Asm->OutStreamer.AddComment("FDE address range"); - EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number), FuncBeginSym); + Asm->EmitLabelDifference(Asm->GetTempSymbol("func_end",DebugFrameInfo.Number), + FuncBeginSym, Asm->getTargetData().getPointerSize()); - EmitFrameMoves(FuncBeginSym, DebugFrameInfo.Moves, false); + Asm->EmitFrameMoves(DebugFrameInfo.Moves, FuncBeginSym, false); Asm->EmitAlignment(2, 0, 0, false); Asm->OutStreamer.EmitLabel(DebugFrameEnd); @@ -2900,22 +2954,24 @@ void DwarfDebug::emitDebugPubNames() { Asm->getObjFileLowering().getDwarfPubNamesSection()); Asm->OutStreamer.AddComment("Length of Public Names Info"); - EmitDifference(getDWLabel("pubnames_end", ModuleCU->getID()), - getDWLabel("pubnames_begin", ModuleCU->getID()), true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("pubnames_end", ModuleCU->getID()), + Asm->GetTempSymbol("pubnames_begin", ModuleCU->getID()), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", + ModuleCU->getID())); Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); - EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), - getTempLabel("section_info"), true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation Unit Length"); - EmitDifference(getDWLabel("info_end", ModuleCU->getID()), - getDWLabel("info_begin", ModuleCU->getID()), - true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", ModuleCU->getID()), + Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + 4); const StringMap<DIE*> &Globals = ModuleCU->getGlobals(); for (StringMap<DIE*>::const_iterator @@ -2926,14 +2982,15 @@ void DwarfDebug::emitDebugPubNames() { Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); - if (Asm->VerboseAsm) + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", + ModuleCU->getID())); } void DwarfDebug::emitDebugPubTypes() { @@ -2941,22 +2998,24 @@ void DwarfDebug::emitDebugPubTypes() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfPubTypesSection()); Asm->OutStreamer.AddComment("Length of Public Types Info"); - EmitDifference(getDWLabel("pubtypes_end", ModuleCU->getID()), - getDWLabel("pubtypes_begin", ModuleCU->getID()), true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("pubtypes_end", ModuleCU->getID()), + Asm->GetTempSymbol("pubtypes_begin", ModuleCU->getID()), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin", + ModuleCU->getID())); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info"); - EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), - getTempLabel("section_info"), true); + Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation ModuleCU Length"); - EmitDifference(getDWLabel("info_end", ModuleCU->getID()), - getDWLabel("info_begin", ModuleCU->getID()), - true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", ModuleCU->getID()), + Asm->GetTempSymbol("info_begin", ModuleCU->getID()), + 4); const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes(); for (StringMap<DIE*>::const_iterator @@ -2964,16 +3023,17 @@ void DwarfDebug::emitDebugPubTypes() { const char *Name = GI->getKeyData(); DIE * Entity = GI->second; - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->getID())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end", + ModuleCU->getID())); } /// emitDebugStr - Emit visible names into a debug str section. @@ -3059,7 +3119,7 @@ void DwarfDebug::emitDebugMacInfo() { /// __debug_info section, and the low_pc is the starting address for the /// inlining instance. void DwarfDebug::emitDebugInlineInfo() { - if (!MAI->doesDwarfUsesInlineInfoSection()) + if (!Asm->MAI->doesDwarfUsesInlineInfoSection()) return; if (!ModuleCU) @@ -3069,15 +3129,15 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->getObjFileLowering().getDwarfDebugInlineSection()); Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry"); - EmitDifference(getDWLabel("debug_inlined_end", 1), - getDWLabel("debug_inlined_begin", 1), true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_inlined_end", 1), + Asm->GetTempSymbol("debug_inlined_begin", 1), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_begin", 1)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1)); Asm->OutStreamer.AddComment("Dwarf Version"); Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(TD->getPointerSize()); + Asm->EmitInt8(Asm->getTargetData().getPointerSize()); for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(), E = InlinedSPNodes.end(); I != E; ++I) { @@ -3095,23 +3155,23 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.EmitBytes(Name, 0); Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator. } else - EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), - getTempLabel("section_str"), true); + Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), + DwarfStrSectionSym); Asm->OutStreamer.AddComment("Function name"); - EmitSectionOffset(getStringPoolEntry(Name), getTempLabel("section_str"), - true); - EmitULEB128(Labels.size(), "Inline count"); + Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym); + Asm->EmitULEB128(Labels.size(), "Inline count"); for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(), LE = Labels.end(); LI != LE; ++LI) { - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(LI->second->getOffset()); - if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("low_pc"); - Asm->OutStreamer.EmitSymbolValue(LI->first, TD->getPointerSize(), 0); + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc"); + Asm->OutStreamer.EmitSymbolValue(LI->first, + Asm->getTargetData().getPointerSize(),0); } } - Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_end", 1)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1)); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 03d9d9935f2f..c7baf5f5d38d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -14,19 +14,14 @@ #ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ -#include "DIE.h" -#include "DwarfPrinter.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Analysis/DebugInfo.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/raw_ostream.h" +#include "DIE.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/UniqueVector.h" -#include <string> +#include "llvm/Support/Allocator.h" namespace llvm { @@ -35,9 +30,27 @@ class DbgConcreteScope; class DbgScope; class DbgVariable; class MachineFrameInfo; +class MachineLocation; class MachineModuleInfo; class MCAsmInfo; class Timer; +class DIEAbbrev; +class DIE; +class DIEBlock; +class DIEEntry; + +class DIEnumerator; +class DIDescriptor; +class DIVariable; +class DIGlobal; +class DIGlobalVariable; +class DISubprogram; +class DIBasicType; +class DIDerivedType; +class DIType; +class DINameSpace; +class DISubrange; +class DICompositeType; //===----------------------------------------------------------------------===// /// SrcLineInfo - This class is used to record source line correspondence. @@ -58,7 +71,13 @@ public: MCSymbol *getLabel() const { return Label; } }; -class DwarfDebug : public DwarfPrinter { +class DwarfDebug { + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + //===--------------------------------------------------------------------===// // Attributes used to construct specific Dwarf sections. // @@ -120,14 +139,6 @@ class DwarfDebug : public DwarfPrinter { /// std::vector<std::vector<SrcLineInfo> > SectionSourceLines; - /// didInitial - Flag to indicate if initial emission has been done. - /// - bool didInitial; - - /// shouldEmit - Flag to indicate if debug information should be emitted. - /// - bool shouldEmit; - // CurrentFnDbgScope - Top level scope for the current function. // DbgScope *CurrentFnDbgScope; @@ -210,6 +221,14 @@ class DwarfDebug : public DwarfPrinter { std::vector<FunctionDebugFrameInfo> DebugFrames; + // Section Symbols: these are assembler temporary labels that are emitted at + // the beginning of each supported dwarf section. These are used to form + // section offsets and are created by EmitSectionLabels. + MCSymbol *DwarfFrameSectionSym, *DwarfInfoSectionSym, *DwarfAbbrevSectionSym; + MCSymbol *DwarfStrSectionSym, *TextSectionSym; + +private: + /// getSourceDirectoryAndFileIds - Return the directory and file ids that /// maps to the source id. Source id starts at 1. std::pair<unsigned, unsigned> @@ -273,10 +292,8 @@ class DwarfDebug : public DwarfPrinter { /// addDIEEntry - Add a DIE attribute data and value. /// - void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry) { - Die->addValue(Attribute, Form, createDIEEntry(Entry)); - } - + void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); + /// addBlock - Add block data. /// void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); @@ -396,9 +413,9 @@ class DwarfDebug : public DwarfPrinter { /// constructScopeDIE - Construct a DIE for this scope. DIE *constructScopeDIE(DbgScope *Scope); - /// emitInitial - Emit initial Dwarf declarations. This is necessary for cc - /// tools to recognize the object file contains Dwarf information. - void emitInitial(); + /// EmitSectionLabels - Emit initial Dwarf sections with a label at + /// the start of each one. + void EmitSectionLabels(); /// emitDIE - Recusively Emits a debug information entry. /// @@ -487,8 +504,8 @@ class DwarfDebug : public DwarfPrinter { /// GetOrCreateSourceID - Look up the source id with the given directory and /// source file names. If none currently exists, create a new id and insert it - /// in the SourceIds map. This can update DirectoryNames and SourceFileNames maps - /// as well. + /// in the SourceIds map. This can update DirectoryNames and SourceFileNames + /// maps as well. unsigned GetOrCreateSourceID(StringRef DirName, StringRef FileName); void constructCompileUnit(MDNode *N); @@ -503,44 +520,17 @@ class DwarfDebug : public DwarfPrinter { /// DIType getBlockByrefType(DIType Ty, std::string Name); -public: - //===--------------------------------------------------------------------===// - // Main entry points. - // - DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); - virtual ~DwarfDebug(); - - /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should - /// be emitted. - bool ShouldEmitDwarfDebug() const { return shouldEmit; } - - /// beginModule - Emit all Dwarf sections that should come prior to the - /// content. - void beginModule(Module *M, MachineModuleInfo *MMI); - - /// endModule - Emit all Dwarf sections that should come after the content. - /// - void endModule(); - - /// beginFunction - Gather pre-function debug information. Assumes being - /// emitted immediately after the function entry point. - void beginFunction(const MachineFunction *MF); - - /// endFunction - Gather and emit post-function debug information. - /// - void endFunction(const MachineFunction *MF); - /// recordSourceLine - Register a source line with debug info. Returns the /// unique label that was emitted and which provides correspondence to /// the source line list. MCSymbol *recordSourceLine(unsigned Line, unsigned Col, MDNode *Scope); - + /// getSourceLineCount - Return the number of source lines in the debug /// info. unsigned getSourceLineCount() const { return Lines.size(); } - + /// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be /// timed. Look up the source id with the given directory and source file /// names. If none currently exists, create a new id and insert it in the @@ -548,13 +538,36 @@ public: /// well. unsigned getOrCreateSourceID(const std::string &DirName, const std::string &FileName); - + /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if atleast one scope was found. bool extractScopeInformation(); - + /// collectVariableInfo - Populate DbgScope entries with variables' info. void collectVariableInfo(); + +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfDebug(AsmPrinter *A, Module *M); + ~DwarfDebug(); + + /// beginModule - Emit all Dwarf sections that should come prior to the + /// content. + void beginModule(Module *M); + + /// endModule - Emit all Dwarf sections that should come after the content. + /// + void endModule(); + + /// beginFunction - Gather pre-function debug information. Assumes being + /// emitted immediately after the function entry point. + void beginFunction(const MachineFunction *MF); + + /// endFunction - Gather and emit post-function debug information. + /// + void endFunction(const MachineFunction *MF); /// beginScope - Process beginning of a scope. void beginScope(const MachineInstr *MI); diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 8b616b012614..72c97a43085c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -13,6 +13,7 @@ #include "DwarfException.h" #include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -27,6 +28,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" @@ -37,9 +39,8 @@ #include "llvm/ADT/Twine.h" using namespace llvm; -DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, - const MCAsmInfo *T) - : DwarfPrinter(OS, A, T), shouldEmitTable(false),shouldEmitMoves(false), +DwarfException::DwarfException(AsmPrinter *A) + : Asm(A), MMI(Asm->MMI), shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false), shouldEmitMovesModule(false), ExceptionTimer(0) { if (TimePassesIsEnabled) @@ -55,10 +56,10 @@ DwarfException::~DwarfException() { /// in every non-empty .debug_frame section. void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // Size and sign of stack growth. - int stackGrowth = - Asm->TM.getFrameInfo()->getStackGrowthDirection() == - TargetFrameInfo::StackGrowsUp ? - TD->getPointerSize() : -TD->getPointerSize(); + int stackGrowth = Asm->getTargetData().getPointerSize(); + if (Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsDown) + stackGrowth *= -1; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); @@ -67,24 +68,25 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { MCSymbol *EHFrameSym; if (TLOF.isFunctionEHFrameSymbolPrivate()) - EHFrameSym = getDWLabel("EH_frame", Index); + EHFrameSym = Asm->GetTempSymbol("EH_frame", Index); else EHFrameSym = Asm->OutContext.GetOrCreateSymbol(Twine("EH_frame") + Twine(Index)); Asm->OutStreamer.EmitLabel(EHFrameSym); - Asm->OutStreamer.EmitLabel(getDWLabel("section_eh_frame", Index)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_eh_frame", Index)); // Define base labels. - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common", Index)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common", Index)); // Define the eh frame length. Asm->OutStreamer.AddComment("Length of Common Information Entry"); - EmitDifference(getDWLabel("eh_frame_common_end", Index), - getDWLabel("eh_frame_common_begin", Index), true); + Asm->EmitLabelDifference(Asm->GetTempSymbol("eh_frame_common_end", Index), + Asm->GetTempSymbol("eh_frame_common_begin", Index), + 4); // EH frame header. - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_begin", Index)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common_begin",Index)); Asm->OutStreamer.AddComment("CIE Identifier Tag"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); Asm->OutStreamer.AddComment("DW_CIE_VERSION"); @@ -105,7 +107,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { if (PersonalityFn) { // There is a personality function. *APtr++ = 'P'; - AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); + AugmentationSize += 1 + Asm->GetSizeOfEncodedValue(PerEncoding); } if (UsesLSDA[Index]) { @@ -127,36 +129,39 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0); // Round out reader. - EmitULEB128(1, "CIE Code Alignment Factor"); - EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->EmitULEB128(1, "CIE Code Alignment Factor"); + Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); Asm->OutStreamer.AddComment("CIE Return Address Column"); + + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); if (Augmentation[0]) { - EmitULEB128(AugmentationSize, "Augmentation Size"); + Asm->EmitULEB128(AugmentationSize, "Augmentation Size"); // If there is a personality, we need to indicate the function's location. if (PersonalityFn) { - EmitEncodingByte(PerEncoding, "Personality"); + Asm->EmitEncodingByte(PerEncoding, "Personality"); Asm->OutStreamer.AddComment("Personality"); - EmitReference(PersonalityFn, PerEncoding); + Asm->EmitReference(PersonalityFn, PerEncoding); } if (UsesLSDA[Index]) - EmitEncodingByte(LSDAEncoding, "LSDA"); + Asm->EmitEncodingByte(LSDAEncoding, "LSDA"); if (FDEEncoding != dwarf::DW_EH_PE_absptr) - EmitEncodingByte(FDEEncoding, "FDE"); + Asm->EmitEncodingByte(FDEEncoding, "FDE"); } // Indicate locations of general callee saved registers in frame. std::vector<MachineMove> Moves; RI->getInitialFrameState(Moves); - EmitFrameMoves(0, Moves, true); + Asm->EmitFrameMoves(Moves, 0, true); // On Darwin the linker honors the alignment of eh_frame, which means it must // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get // holes which confuse readers of eh_frame. - Asm->EmitAlignment(TD->getPointerSize() == 4 ? 2 : 3, 0, 0, false); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_end", Index)); + Asm->EmitAlignment(Asm->getTargetData().getPointerSize() == 4 ? 2 : 3, + 0, 0, false); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common_end", Index)); } /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. @@ -178,13 +183,13 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,MCSA_Global); // If corresponding function is weak definition, this should be too. - if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) + if (TheFunc->isWeakForLinker() && Asm->MAI->getWeakDefDirective()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_WeakDefinition); // If corresponding function is hidden, this should be too. if (TheFunc->hasHiddenVisibility()) - if (MCSymbolAttr HiddenAttr = MAI->getHiddenVisibilityAttr()) + if (MCSymbolAttr HiddenAttr = Asm->MAI->getHiddenVisibilityAttr()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, HiddenAttr); @@ -194,14 +199,14 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // info is to be available for non-EH uses. if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && (!TheFunc->isWeakForLinker() || - !MAI->getWeakDefDirective() || + !Asm->MAI->getWeakDefDirective() || TLOF.getSupportsWeakOmittedEHFrame())) { Asm->OutStreamer.EmitAssignment(EHFrameInfo.FunctionEHSym, MCConstantExpr::Create(0, Asm->OutContext)); // This name has no connection to the function, so it might get // dead-stripped when the function is not, erroneously. Prohibit // dead-stripping unconditionally. - if (MAI->hasNoDeadStrip()) + if (Asm->MAI->hasNoDeadStrip()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_NoDeadStrip); } else { @@ -209,52 +214,58 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // EH frame header. Asm->OutStreamer.AddComment("Length of Frame Information Entry"); - EmitDifference(getDWLabel("eh_frame_end", EHFrameInfo.Number), - getDWLabel("eh_frame_begin", EHFrameInfo.Number), - true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("eh_frame_end", EHFrameInfo.Number), + Asm->GetTempSymbol("eh_frame_begin", EHFrameInfo.Number), 4); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_begin",EHFrameInfo.Number)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_begin", + EHFrameInfo.Number)); Asm->OutStreamer.AddComment("FDE CIE offset"); - EmitSectionOffset(getDWLabel("eh_frame_begin", EHFrameInfo.Number), - getDWLabel("eh_frame_common", - EHFrameInfo.PersonalityIndex), - true, true); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("eh_frame_begin", EHFrameInfo.Number), + Asm->GetTempSymbol("eh_frame_common", + EHFrameInfo.PersonalityIndex), 4); - MCSymbol *EHFuncBeginSym = getDWLabel("eh_func_begin", EHFrameInfo.Number); + MCSymbol *EHFuncBeginSym = + Asm->GetTempSymbol("eh_func_begin", EHFrameInfo.Number); Asm->OutStreamer.AddComment("FDE initial location"); - EmitReference(EHFuncBeginSym, FDEEncoding); + Asm->EmitReference(EHFuncBeginSym, FDEEncoding); Asm->OutStreamer.AddComment("FDE address range"); - EmitDifference(getDWLabel("eh_func_end", EHFrameInfo.Number),EHFuncBeginSym, - SizeOfEncodedValue(FDEEncoding) == 4); + Asm->EmitLabelDifference(Asm->GetTempSymbol("eh_func_end", + EHFrameInfo.Number), + EHFuncBeginSym, + Asm->GetSizeOfEncodedValue(FDEEncoding)); // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { - unsigned Size = SizeOfEncodedValue(LSDAEncoding); + unsigned Size = Asm->GetSizeOfEncodedValue(LSDAEncoding); - EmitULEB128(Size, "Augmentation size"); + Asm->EmitULEB128(Size, "Augmentation size"); Asm->OutStreamer.AddComment("Language Specific Data Area"); if (EHFrameInfo.hasLandingPads) - EmitReference(getDWLabel("exception", EHFrameInfo.Number),LSDAEncoding); + Asm->EmitReference(Asm->GetTempSymbol("exception", EHFrameInfo.Number), + LSDAEncoding); else Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); } else { - EmitULEB128(0, "Augmentation size"); + Asm->EmitULEB128(0, "Augmentation size"); } // Indicate locations of function specific callee saved registers in frame. - EmitFrameMoves(EHFuncBeginSym, EHFrameInfo.Moves, true); + Asm->EmitFrameMoves(EHFrameInfo.Moves, EHFuncBeginSym, true); // On Darwin the linker honors the alignment of eh_frame, which means it // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you // get holes which confuse readers of eh_frame. - Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, + Asm->EmitAlignment(Asm->getTargetData().getPointerSize() == 4 ? 2 : 3, 0, 0, false); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_end", EHFrameInfo.Number)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_end", + EHFrameInfo.Number)); // If the function is marked used, this table should be also. We cannot // make the mark unconditional in this case, since retaining the table also @@ -262,7 +273,7 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // on unused functions (calling undefined externals) being dead-stripped to // link correctly. Yes, there really is. if (MMI->isUsedFunction(EHFrameInfo.function)) - if (MAI->hasNoDeadStrip()) + if (Asm->MAI->hasNoDeadStrip()) Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, MCSA_NoDeadStrip); } @@ -348,7 +359,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { const LandingPadInfo *LPI = *I; const std::vector<int> &TypeIds = LPI->TypeIds; - const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; + unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; unsigned SizeSiteActions = 0; if (NumShared < TypeIds.size()) { @@ -356,7 +367,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, unsigned PrevAction = (unsigned)-1; if (NumShared) { - const unsigned SizePrevIds = PrevLPI->TypeIds.size(); + unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = Actions.size() - 1; SizeAction = @@ -465,7 +476,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, bool PreviousIsInvoke = false; // Visit all instructions in order of address. - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { @@ -496,7 +507,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // create a call-site entry with no landing pad for the region between the // try-ranges. if (SawPotentiallyThrowing && - MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; @@ -519,7 +530,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // Try to merge with the previous call-site. SJLJ doesn't do this if (PreviousIsInvoke && - MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. @@ -529,7 +540,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, } // Otherwise, create a new call-site. - if (MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) + if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) CallSites.push_back(Site); else { // SjLj EH must maintain the call sites in the order assigned @@ -548,7 +559,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // function may throw, create a call-site entry with no landing pad for the // region following the try-range. if (SawPotentiallyThrowing && - MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { CallSiteEntry Site = { LastLabel, 0, 0, 0 }; CallSites.push_back(Site); } @@ -616,18 +627,19 @@ void DwarfException::EmitExceptionTable() { // Final tallies. // Call sites. - const unsigned SiteStartSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); - const unsigned SiteLengthSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); - const unsigned LandingPadSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); - bool IsSJLJ = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; + unsigned CallSiteTableLength; - if (IsSJLJ) CallSiteTableLength = 0; - else - CallSiteTableLength = CallSites.size() * - (SiteStartSize + SiteLengthSize + LandingPadSize); + else { + unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 + unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 + unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 + CallSiteTableLength = + CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); + } for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); @@ -644,7 +656,8 @@ void DwarfException::EmitExceptionTable() { // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say // that we're omitting that bit. TTypeEncoding = dwarf::DW_EH_PE_omit; - TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); + // dwarf::DW_EH_PE_absptr + TypeFormatSize = Asm->getTargetData().getPointerSize(); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to // pick a type encoding for them. We're about to emit a list of pointers to @@ -674,7 +687,7 @@ void DwarfException::EmitExceptionTable() { // in target-independent code. // TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); - TypeFormatSize = SizeOfEncodedValue(TTypeEncoding); + TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); } // Begin the exception table. @@ -684,16 +697,18 @@ void DwarfException::EmitExceptionTable() { // Emit the LSDA. MCSymbol *GCCETSym = Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+ - Twine(SubprogramCount)); + Twine(Asm->getFunctionNumber())); Asm->OutStreamer.EmitLabel(GCCETSym); - Asm->OutStreamer.EmitLabel(getDWLabel("exception", SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception", + Asm->getFunctionNumber())); if (IsSJLJ) - Asm->OutStreamer.EmitLabel(getDWLabel("_LSDA_", Asm->getFunctionNumber())); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_", + Asm->getFunctionNumber())); // Emit the LSDA header. - EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); - EmitEncodingByte(TTypeEncoding, "@TType"); + Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); + Asm->EmitEncodingByte(TTypeEncoding, "@TType"); // The type infos need to be aligned. GCC does this by inserting padding just // before the type infos. However, this changes the size of the exception @@ -730,16 +745,16 @@ void DwarfException::EmitExceptionTable() { if (HaveTTData) { // Account for any extra padding that will be added to the call site table // length. - EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); + Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); SizeAlign = 0; } // SjLj Exception handling if (IsSJLJ) { - EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); // Add extra padding if it wasn't added to the TType base offset. - EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); + Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); // Emit the landing pad site information. unsigned idx = 0; @@ -749,16 +764,16 @@ void DwarfException::EmitExceptionTable() { // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - EmitULEB128(idx, "Landing pad"); + Asm->EmitULEB128(idx, "Landing pad"); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. - EmitULEB128(S.Action, "Action"); + Asm->EmitULEB128(S.Action, "Action"); } } else { // DWARF Exception handling - assert(MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); + assert(Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); // The call-site table is a list of all call sites that may throw an // exception (including C++ 'throw' statements) in the procedure @@ -779,32 +794,33 @@ void DwarfException::EmitExceptionTable() { // supposed to throw. // Emit the landing pad call site table. - EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); // Add extra padding if it wasn't added to the TType base offset. - EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); + Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { const CallSiteEntry &S = *I; - MCSymbol *EHFuncBeginSym = getDWLabel("eh_func_begin", SubprogramCount); + MCSymbol *EHFuncBeginSym = + Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); MCSymbol *BeginLabel = S.BeginLabel; if (BeginLabel == 0) BeginLabel = EHFuncBeginSym; MCSymbol *EndLabel = S.EndLabel; if (EndLabel == 0) - EndLabel = getDWLabel("eh_func_end", SubprogramCount); + EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); // Offset of the call site relative to the previous call site, counted in // number of 16-byte bundles. The first call site is counted relative to // the start of the procedure fragment. Asm->OutStreamer.AddComment("Region start"); - EmitSectionOffset(BeginLabel, EHFuncBeginSym, true, true); + Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); Asm->OutStreamer.AddComment("Region length"); - EmitDifference(EndLabel, BeginLabel, true); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Offset of the landing pad, counted in 16-byte bundles relative to the @@ -813,12 +829,12 @@ void DwarfException::EmitExceptionTable() { if (!S.PadLabel) Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); else - EmitSectionOffset(S.PadLabel, EHFuncBeginSym, true, true); + Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. - EmitULEB128(S.Action, "Action"); + Asm->EmitULEB128(S.Action, "Action"); } } @@ -838,13 +854,13 @@ void DwarfException::EmitExceptionTable() { // // Used by the runtime to match the type of the thrown exception to the // type of the catch clauses or the types in the exception specification. - EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); + Asm->EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); // Action Record // // Self-relative signed displacement in bytes of the next action record, // or 0 if there is no next action record. - EmitSLEB128(Action.NextAction, " Next action"); + Asm->EmitSLEB128(Action.NextAction, " Next action"); } // Emit the Catch TypeInfos. @@ -858,9 +874,10 @@ void DwarfException::EmitExceptionTable() { Asm->OutStreamer.AddComment("TypeInfo"); if (GV) - EmitReference(GV, TTypeEncoding); + Asm->EmitReference(GV, TTypeEncoding); else - Asm->OutStreamer.EmitIntValue(0, SizeOfEncodedValue(TTypeEncoding), 0); + Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding), + 0); } // Emit the Exception Specifications. @@ -871,7 +888,7 @@ void DwarfException::EmitExceptionTable() { for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; - EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); + Asm->EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); } Asm->EmitAlignment(2, 0, 0, false); @@ -880,7 +897,7 @@ void DwarfException::EmitExceptionTable() { /// EndModule - Emit all exception information that should come after the /// content. void DwarfException::EndModule() { - if (MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) + if (Asm->MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) return; if (!shouldEmitMovesModule && !shouldEmitTableModule) @@ -901,21 +918,20 @@ void DwarfException::EndModule() { /// BeginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. void DwarfException::BeginFunction(const MachineFunction *MF) { - if (!MMI || !MAI->doesSupportExceptionHandling()) return; - TimeRegion Timer(ExceptionTimer); - this->MF = MF; shouldEmitTable = shouldEmitMoves = false; // If any landing pads survive, we need an EH table. shouldEmitTable = !MMI->getLandingPads().empty(); // See if we need frame move info. - shouldEmitMoves = !MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; + shouldEmitMoves = + !Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; if (shouldEmitMoves || shouldEmitTable) // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_begin", ++SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); shouldEmitTableModule |= shouldEmitTable; shouldEmitMovesModule |= shouldEmitMoves; @@ -927,7 +943,8 @@ void DwarfException::EndFunction() { if (!shouldEmitMoves && !shouldEmitTable) return; TimeRegion Timer(ExceptionTimer); - Asm->OutStreamer.EmitLabel(getDWLabel("eh_func_end", SubprogramCount)); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", + Asm->getFunctionNumber())); // Record if this personality index uses a landing pad. bool HasLandingPad = !MMI->getLandingPads().empty(); @@ -941,14 +958,15 @@ void DwarfException::EndFunction() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); MCSymbol *FunctionEHSym = - Asm->GetSymbolWithGlobalValueBase(MF->getFunction(), ".eh", + Asm->GetSymbolWithGlobalValueBase(Asm->MF->getFunction(), ".eh", TLOF.isFunctionEHFrameSymbolPrivate()); // Save EH frame information - EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, SubprogramCount, + EHFrames.push_back(FunctionEHFrameInfo(FunctionEHSym, + Asm->getFunctionNumber(), MMI->getPersonalityIndex(), - MF->getFrameInfo()->hasCalls(), + Asm->MF->getFrameInfo()->hasCalls(), !MMI->getLandingPads().empty(), MMI->getFrameMoves(), - MF->getFunction())); + Asm->MF->getFunction())); } diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 4bc4a458c04e..f35c0b616c1f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -14,25 +14,34 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H #define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H -#include "DIE.h" -#include "DwarfPrinter.h" -#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/ADT/DenseMap.h" -#include <string> +#include <vector> namespace llvm { +template <typename T> class SmallVectorImpl; struct LandingPadInfo; class MachineModuleInfo; +class MachineMove; +class MachineInstr; +class MachineFunction; class MCAsmInfo; class MCExpr; +class MCSymbol; class Timer; -class raw_ostream; +class Function; +class AsmPrinter; //===----------------------------------------------------------------------===// /// DwarfException - Emits Dwarf exception handling directives. /// -class DwarfException : public DwarfPrinter { +class DwarfException { + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + struct FunctionEHFrameInfo { MCSymbol *FunctionEHSym; // L_foo.eh unsigned Number; @@ -166,15 +175,8 @@ public: //===--------------------------------------------------------------------===// // Main entry points. // - DwarfException(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); - virtual ~DwarfException(); - - /// BeginModule - Emit all exception information that should come prior to the - /// content. - void BeginModule(Module *m, MachineModuleInfo *mmi) { - this->M = m; - this->MMI = mmi; - } + DwarfException(AsmPrinter *A); + ~DwarfException(); /// EndModule - Emit all exception information that should come after the /// content. diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp deleted file mode 100644 index 17eb2e872742..000000000000 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ /dev/null @@ -1,308 +0,0 @@ -//===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Emit general DWARF directives. -// -//===----------------------------------------------------------------------===// - -#include "DwarfPrinter.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetFrameInfo.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/ADT/SmallString.h" -using namespace llvm; - -DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T) -: O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()), - RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), - SubprogramCount(0) {} - - -/// getDWLabel - Return the MCSymbol corresponding to the assembler temporary -/// label with the specified stem and unique ID. -MCSymbol *DwarfPrinter::getDWLabel(const char *Name, unsigned ID) const { - // FIXME: REMOVE this. However, there is stuff in EH that passes counters in - // here that can be zero. - - //assert(ID && "Should use getTempLabel if no ID"); - if (ID == 0) return getTempLabel(Name); - return Asm->OutContext.GetOrCreateSymbol - (Twine(MAI->getPrivateGlobalPrefix()) + Twine(Name) + Twine(ID)); -} - -/// getTempLabel - Return the MCSymbol corresponding to the assembler temporary -/// label with the specified name. -MCSymbol *DwarfPrinter::getTempLabel(const char *Name) const { - return Asm->OutContext.GetOrCreateSymbol - (Twine(MAI->getPrivateGlobalPrefix()) + Name); -} - - -/// SizeOfEncodedValue - Return the size of the encoding in bytes. -unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { - if (Encoding == dwarf::DW_EH_PE_omit) - return 0; - - switch (Encoding & 0x07) { - case dwarf::DW_EH_PE_absptr: - return TD->getPointerSize(); - case dwarf::DW_EH_PE_udata2: - return 2; - case dwarf::DW_EH_PE_udata4: - return 4; - case dwarf::DW_EH_PE_udata8: - return 8; - } - - assert(0 && "Invalid encoded value."); - return 0; -} - -static const char *DecodeDWARFEncoding(unsigned Encoding) { - switch (Encoding) { - case dwarf::DW_EH_PE_absptr: return "absptr"; - case dwarf::DW_EH_PE_omit: return "omit"; - case dwarf::DW_EH_PE_pcrel: return "pcrel"; - case dwarf::DW_EH_PE_udata4: return "udata4"; - case dwarf::DW_EH_PE_udata8: return "udata8"; - case dwarf::DW_EH_PE_sdata4: return "sdata4"; - case dwarf::DW_EH_PE_sdata8: return "sdata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: - return "indirect pcrel udata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: - return "indirect pcrel sdata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: - return "indirect pcrel udata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: - return "indirect pcrel sdata8"; - } - - return "<unknown encoding>"; -} - -/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an -/// encoding. If verbose assembly output is enabled, we output comments -/// describing the encoding. Desc is an optional string saying what the -/// encoding is specifying (e.g. "LSDA"). -void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) { - if (Asm->VerboseAsm) { - if (Desc != 0) - Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " + - Twine(DecodeDWARFEncoding(Val))); - else - Asm->OutStreamer.AddComment(Twine("Encoding = ") + - DecodeDWARFEncoding(Val)); - } - - Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); -} - -/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. -void DwarfPrinter::EmitCFAByte(unsigned Val) { - if (Asm->VerboseAsm) { - if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) - Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" + - Twine(Val-dwarf::DW_CFA_offset) + ")"); - else - Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val)); - } - Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); -} - -/// EmitSLEB128 - emit the specified signed leb128 value. -void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const { - if (Asm->VerboseAsm && Desc) - Asm->OutStreamer.AddComment(Desc); - - if (MAI->hasLEB128()) { - // FIXME: MCize. - O << "\t.sleb128\t" << Value; - Asm->OutStreamer.AddBlankLine(); - return; - } - - // If we don't have .sleb128, emit as .bytes. - int Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); - } while (IsMore); -} - -/// EmitULEB128 - emit the specified signed leb128 value. -void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc, - unsigned PadTo) const { - if (Asm->VerboseAsm && Desc) - Asm->OutStreamer.AddComment(Desc); - - if (MAI->hasLEB128() && PadTo == 0) { - // FIXME: MCize. - O << "\t.uleb128\t" << Value; - Asm->OutStreamer.AddBlankLine(); - return; - } - - // If we don't have .uleb128 or we want to emit padding, emit as .bytes. - do { - unsigned char Byte = static_cast<unsigned char>(Value & 0x7f); - Value >>= 7; - if (Value || PadTo != 0) Byte |= 0x80; - Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); - } while (Value); - - if (PadTo) { - if (PadTo > 1) - Asm->OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); - Asm->OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); - } -} - - -void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - - const MCExpr *Exp = TLOF.getExprForDwarfReference(Sym, Asm->Mang, - Asm->MMI, Encoding, - Asm->OutStreamer); - Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0); -} - -void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - - const MCExpr *Exp = - TLOF.getExprForDwarfGlobalReference(GV, Asm->Mang, Asm->MMI, Encoding, - Asm->OutStreamer); - Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0); -} - -/// EmitDifference - Emit the difference between two labels. If this assembler -/// supports .set, we emit a .set of a temporary and then use it in the .word. -void DwarfPrinter::EmitDifference(const MCSymbol *TagHi, const MCSymbol *TagLo, - bool IsSmall) { - unsigned Size = IsSmall ? 4 : TD->getPointerSize(); - Asm->EmitLabelDifference(TagHi, TagLo, Size); -} - -void DwarfPrinter::EmitSectionOffset(const MCSymbol *Label, - const MCSymbol *Section, - bool IsSmall, bool isEH) { - bool isAbsolute; - if (isEH) - isAbsolute = MAI->isAbsoluteEHSectionOffsets(); - else - isAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - - if (!isAbsolute) - return EmitDifference(Label, Section, IsSmall); - - // On COFF targets, we have to emit the weird .secrel32 directive. - if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { - // FIXME: MCize. - Asm->O << SecOffDir << Label->getName(); - Asm->OutStreamer.AddBlankLine(); - } else { - unsigned Size = IsSmall ? 4 : TD->getPointerSize(); - Asm->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/); - } -} - -/// EmitFrameMoves - Emit frame instructions to describe the layout of the -/// frame. -void DwarfPrinter::EmitFrameMoves(MCSymbol *BaseLabel, - const std::vector<MachineMove> &Moves, - bool isEH) { - int stackGrowth = TD->getPointerSize(); - if (Asm->TM.getFrameInfo()->getStackGrowthDirection() != - TargetFrameInfo::StackGrowsUp) - stackGrowth *= -1; - - for (unsigned i = 0, N = Moves.size(); i < N; ++i) { - const MachineMove &Move = Moves[i]; - MCSymbol *Label = Move.getLabel(); - // Throw out move if the label is invalid. - if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. - - const MachineLocation &Dst = Move.getDestination(); - const MachineLocation &Src = Move.getSource(); - - // Advance row if new location. - if (BaseLabel && Label) { - MCSymbol *ThisSym = Label; - if (ThisSym != BaseLabel) { - EmitCFAByte(dwarf::DW_CFA_advance_loc4); - EmitDifference(ThisSym, BaseLabel, true); - BaseLabel = ThisSym; - } - } - - // If advancing cfa. - if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { - if (!Src.isReg()) { - if (Src.getReg() == MachineLocation::VirtualFP) { - EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); - } else { - EmitCFAByte(dwarf::DW_CFA_def_cfa); - EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); - } - - int Offset = -Src.getOffset(); - EmitULEB128(Offset, "Offset"); - } else { - llvm_unreachable("Machine move not supported yet."); - } - } else if (Src.isReg() && - Src.getReg() == MachineLocation::VirtualFP) { - if (Dst.isReg()) { - EmitCFAByte(dwarf::DW_CFA_def_cfa_register); - EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); - } else { - llvm_unreachable("Machine move not supported yet."); - } - } else { - unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); - int Offset = Dst.getOffset() / stackGrowth; - - if (Offset < 0) { - EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); - EmitULEB128(Reg, "Reg"); - EmitSLEB128(Offset, "Offset"); - } else if (Reg < 64) { - EmitCFAByte(dwarf::DW_CFA_offset + Reg); - EmitULEB128(Offset, "Offset"); - } else { - EmitCFAByte(dwarf::DW_CFA_offset_extended); - EmitULEB128(Reg, "Reg"); - EmitULEB128(Offset, "Offset"); - } - } - } -} diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h deleted file mode 100644 index 0b94645a8c7b..000000000000 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ /dev/null @@ -1,131 +0,0 @@ -//===--- lib/CodeGen/DwarfPrinter.h - Dwarf Printer -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Emit general DWARF directives. -// -//===----------------------------------------------------------------------===// - -#ifndef CODEGEN_ASMPRINTER_DWARFPRINTER_H__ -#define CODEGEN_ASMPRINTER_DWARFPRINTER_H__ - -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/FormattedStream.h" -#include <vector> - -namespace llvm { -class AsmPrinter; -class MachineFunction; -class MachineModuleInfo; -class Module; -class MCAsmInfo; -class TargetData; -class TargetRegisterInfo; -class GlobalValue; -class MCSymbol; -class Twine; - -class DwarfPrinter { -protected: - ~DwarfPrinter() {} - - //===-------------------------------------------------------------==---===// - // Core attributes used by the DWARF printer. - // - - /// O - Stream to .s file. - raw_ostream &O; - - /// Asm - Target of Dwarf emission. - AsmPrinter *Asm; - - /// MAI - Target asm information. - const MCAsmInfo *MAI; - - /// TD - Target data. - const TargetData *TD; - - /// RI - Register Information. - const TargetRegisterInfo *RI; - - /// M - Current module. - Module *M; - - /// MF - Current machine function. - const MachineFunction *MF; - - /// MMI - Collected machine module information. - MachineModuleInfo *MMI; - - /// SubprogramCount - The running count of functions being compiled. - unsigned SubprogramCount; - - DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T); -public: - - //===------------------------------------------------------------------===// - // Accessors. - // - const AsmPrinter *getAsm() const { return Asm; } - MachineModuleInfo *getMMI() const { return MMI; } - const MCAsmInfo *getMCAsmInfo() const { return MAI; } - const TargetData *getTargetData() const { return TD; } - - /// getDWLabel - Return the MCSymbol corresponding to the assembler temporary - /// label with the specified stem and unique ID. - MCSymbol *getDWLabel(const char *Name, unsigned ID) const; - - /// getTempLabel - Return an assembler temporary label with the specified - /// name. - MCSymbol *getTempLabel(const char *Name) const; - - /// SizeOfEncodedValue - Return the size of the encoding in bytes. - unsigned SizeOfEncodedValue(unsigned Encoding) const; - - /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an - /// encoding. If verbose assembly output is enabled, we output comments - /// describing the encoding. Desc is a string saying what the encoding is - /// specifying (e.g. "LSDA"). - void EmitEncodingByte(unsigned Val, const char *Desc); - - /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. - void EmitCFAByte(unsigned Val); - - - /// EmitSLEB128 - emit the specified signed leb128 value. - void EmitSLEB128(int Value, const char *Desc) const; - - /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(unsigned Value, const char *Desc = 0, - unsigned PadTo = 0) const; - - - /// EmitReference - Emit a reference to a label. - /// - void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; - void EmitReference(const GlobalValue *GV, unsigned Encoding) const; - - /// EmitDifference - Emit the difference between two labels. - void EmitDifference(const MCSymbol *LabelHi, const MCSymbol *LabelLo, - bool IsSmall = false); - - /// EmitSectionOffset - Emit Label-Section or use a special purpose directive - /// to emit a section offset if the target has one. - void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *Section, - bool IsSmall = false, bool isEH = false); - - /// EmitFrameMoves - Emit frame instructions to describe the layout of the - /// frame. - void EmitFrameMoves(MCSymbol *BaseLabel, - const std::vector<MachineMove> &Moves, bool isEH); -}; - -} // end llvm namespace - -#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp deleted file mode 100644 index a2d7ab1224ee..000000000000 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//===-- llvm/CodeGen/DwarfWriter.cpp - Dwarf Framework --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for writing dwarf info into asm files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/DwarfWriter.h" -#include "DwarfDebug.h" -#include "DwarfException.h" -#include "llvm/CodeGen/MachineModuleInfo.h" - -using namespace llvm; - -static RegisterPass<DwarfWriter> -X("dwarfwriter", "DWARF Information Writer"); -char DwarfWriter::ID = 0; - -//===----------------------------------------------------------------------===// -/// DwarfWriter Implementation -/// - -DwarfWriter::DwarfWriter() - : ImmutablePass(&ID), DD(0), DE(0) {} - -DwarfWriter::~DwarfWriter() { - delete DE; - delete DD; -} - -/// BeginModule - Emit all Dwarf sections that should come prior to the -/// content. -void DwarfWriter::BeginModule(Module *M, - MachineModuleInfo *MMI, - raw_ostream &OS, AsmPrinter *A, - const MCAsmInfo *T) { - DE = new DwarfException(OS, A, T); - DD = new DwarfDebug(OS, A, T); - DE->BeginModule(M, MMI); - DD->beginModule(M, MMI); -} - -/// EndModule - Emit all Dwarf sections that should come after the content. -/// -void DwarfWriter::EndModule() { - DE->EndModule(); - DD->endModule(); - delete DD; DD = 0; - delete DE; DE = 0; -} - -/// BeginFunction - Gather pre-function debug information. Assumes being -/// emitted immediately after the function entry point. -void DwarfWriter::BeginFunction(const MachineFunction *MF) { - DE->BeginFunction(MF); - DD->beginFunction(MF); -} - -/// EndFunction - Gather and emit post-function debug information. -/// -void DwarfWriter::EndFunction(const MachineFunction *MF) { - DD->endFunction(MF); - DE->EndFunction(); - - if (MachineModuleInfo *MMI = DD->getMMI() ? DD->getMMI() : DE->getMMI()) - // Clear function debug information. - MMI->EndFunction(); -} - -/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should -/// be emitted. -bool DwarfWriter::ShouldEmitDwarfDebug() const { - return DD && DD->ShouldEmitDwarfDebug(); -} - -void DwarfWriter::BeginScope(const MachineInstr *MI) { - DD->beginScope(MI); -} -void DwarfWriter::EndScope(const MachineInstr *MI) { - DD->endScope(MI); -} diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index fa840e133a5e..1db178f020ec 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -16,11 +16,14 @@ #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/Module.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" using namespace llvm; @@ -29,11 +32,8 @@ namespace { class OcamlGCMetadataPrinter : public GCMetadataPrinter { public: - void beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI); - - void finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI); + void beginAssembly(AsmPrinter &AP); + void finishAssembly(AsmPrinter &AP); }; } @@ -43,33 +43,34 @@ Y("ocaml", "ocaml 3.10-compatible collector"); void llvm::linkOcamlGCPrinter() { } -static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI, const char *Id) { +static void EmitCamlGlobal(const Module &M, AsmPrinter &AP, const char *Id) { const std::string &MId = M.getModuleIdentifier(); - std::string Mangled; - Mangled += MAI.getGlobalPrefix(); - Mangled += "caml"; - size_t Letter = Mangled.size(); - Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); - Mangled += "__"; - Mangled += Id; - + std::string SymName; + SymName += "caml"; + size_t Letter = SymName.size(); + SymName.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); + SymName += "__"; + SymName += Id; + // Capitalize the first letter of the module name. - Mangled[Letter] = toupper(Mangled[Letter]); - - if (const char *GlobalDirective = MAI.getGlobalDirective()) - OS << GlobalDirective << Mangled << "\n"; - OS << Mangled << ":\n"; + SymName[Letter] = toupper(SymName[Letter]); + + SmallString<128> TmpStr; + AP.Mang->getNameWithPrefix(TmpStr, SymName); + + MCSymbol *Sym = AP.OutContext.GetOrCreateSymbol(TmpStr); + + AP.OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); + AP.OutStreamer.EmitLabel(Sym); } -void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { +void OcamlGCMetadataPrinter::beginAssembly(AsmPrinter &AP) { AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "code_begin"); + EmitCamlGlobal(getModule(), AP, "code_begin"); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "data_begin"); + EmitCamlGlobal(getModule(), AP, "data_begin"); } /// emitAssembly - Print the frametable. The ocaml frametable format is thus: @@ -88,28 +89,20 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, /// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if /// either condition is detected in a function which uses the GC. /// -void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { - const char *AddressDirective; - int AddressAlignLog; - if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) { - AddressDirective = MAI.getData32bitsDirective(); - AddressAlignLog = 2; - } else { - AddressDirective = MAI.getData64bitsDirective(); - AddressAlignLog = 3; - } +void OcamlGCMetadataPrinter::finishAssembly(AsmPrinter &AP) { + unsigned IntPtrSize = AP.TM.getTargetData()->getPointerSize(); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "code_end"); + EmitCamlGlobal(getModule(), AP, "code_end"); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "data_end"); + EmitCamlGlobal(getModule(), AP, "data_end"); - OS << AddressDirective << 0 << '\n'; // FIXME: Why does ocaml emit this?? + // FIXME: Why does ocaml emit this?? + AP.OutStreamer.EmitIntValue(0, IntPtrSize, 0); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); - EmitCamlGlobal(getModule(), OS, AP, MAI, "frametable"); + EmitCamlGlobal(getModule(), AP, "frametable"); for (iterator I = begin(), IE = end(); I != IE; ++I) { GCFunctionInfo &FI = **I; @@ -125,8 +118,9 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, llvm_report_error(Msg.str()); // Very rude! } - OS << "\t" << MAI.getCommentString() << " live roots for " - << FI.getFunction().getName() << "\n"; + AP.OutStreamer.AddComment("live roots for " + + Twine(FI.getFunction().getName())); + AP.OutStreamer.AddBlankLine(); for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { size_t LiveCount = FI.live_size(J); @@ -139,10 +133,8 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, llvm_report_error(Msg.str()); // Very rude! } - OS << AddressDirective << J->Label->getName() << '\n'; - + AP.OutStreamer.EmitSymbolValue(J->Label, IntPtrSize, 0); AP.EmitInt16(FrameSize); - AP.EmitInt16(LiveCount); for (GCFunctionInfo::live_iterator K = FI.live_begin(J), @@ -154,7 +146,7 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, AP.EmitInt32(K->StackOffset); } - AP.EmitAlignment(AddressAlignLog); + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); } } } diff --git a/lib/CodeGen/GCMetadataPrinter.cpp b/lib/CodeGen/GCMetadataPrinter.cpp index 752752f71ba3..f80e9ced0bc9 100644 --- a/lib/CodeGen/GCMetadataPrinter.cpp +++ b/lib/CodeGen/GCMetadataPrinter.cpp @@ -18,12 +18,10 @@ GCMetadataPrinter::GCMetadataPrinter() { } GCMetadataPrinter::~GCMetadataPrinter() { } -void GCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { +void GCMetadataPrinter::beginAssembly(AsmPrinter &AP) { // Default is no action. } -void GCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, - const MCAsmInfo &MAI) { +void GCMetadataPrinter::finishAssembly(AsmPrinter &AP) { // Default is no action. } diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 75e45efe4de1..ed57f4cb101f 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -123,18 +123,15 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, const MCAsmInfo &MAI = *getMCAsmInfo(); OwningPtr<MCStreamer> AsmStreamer; - formatted_raw_ostream *LegacyOutput; switch (FileType) { default: return true; case CGFT_AssemblyFile: { MCInstPrinter *InstPrinter = - getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, Out); + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); AsmStreamer.reset(createAsmStreamer(*Context, Out, getTargetData()->isLittleEndian(), getVerboseAsm(), InstPrinter, /*codeemitter*/0)); - // Set the AsmPrinter's "O" to the output file. - LegacyOutput = &Out; break; } case CGFT_ObjectFile: { @@ -146,29 +143,17 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, return true; AsmStreamer.reset(createMachOStreamer(*Context, *TAB, Out, MCE)); - - // Any output to the asmprinter's "O" stream is bad and needs to be fixed, - // force it to come out stderr. - // FIXME: this is horrible and leaks, eventually remove the raw_ostream from - // asmprinter. - LegacyOutput = new formatted_raw_ostream(errs()); break; } case CGFT_Null: // The Null output is intended for use for performance analysis and testing, // not real users. AsmStreamer.reset(createNullStreamer(*Context)); - // Any output to the asmprinter's "O" stream is bad and needs to be fixed, - // force it to come out stderr. - // FIXME: this is horrible and leaks, eventually remove the raw_ostream from - // asmprinter. - LegacyOutput = new formatted_raw_ostream(errs()); break; } // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. - FunctionPass *Printer = - getTarget().createAsmPrinter(*LegacyOutput, *this, *AsmStreamer); + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); if (Printer == 0) return true; diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index beac0c630bb5..e4ed7dbac4e7 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/MC/MCAsmInfo.h" @@ -51,8 +52,8 @@ void ilist_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) { } MachineFunction::MachineFunction(Function *F, const TargetMachine &TM, - unsigned FunctionNum, MCContext &ctx) - : Fn(F), Target(TM), Ctx(ctx) { + unsigned FunctionNum, MachineModuleInfo &mmi) + : Fn(F), Target(TM), Ctx(mmi.getContext()), MMI(mmi) { if (TM.getRegisterInfo()) RegInfo = new (Allocator) MachineRegisterInfo(*TM.getRegisterInfo()); else diff --git a/lib/CodeGen/MachineFunctionAnalysis.cpp b/lib/CodeGen/MachineFunctionAnalysis.cpp index d3f1d8296daa..3b2eb6d388b4 100644 --- a/lib/CodeGen/MachineFunctionAnalysis.cpp +++ b/lib/CodeGen/MachineFunctionAnalysis.cpp @@ -35,10 +35,23 @@ MachineFunctionAnalysis::~MachineFunctionAnalysis() { assert(!MF && "MachineFunctionAnalysis left initialized!"); } +void MachineFunctionAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<MachineModuleInfo>(); +} + +bool MachineFunctionAnalysis::doInitialization(Module &M) { + MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>(); + assert(MMI && "MMI not around yet??"); + MMI->setModule(&M); + NextFnNum = 1; return false; +} + + bool MachineFunctionAnalysis::runOnFunction(Function &F) { assert(!MF && "MachineFunctionAnalysis already initialized!"); MF = new MachineFunction(&F, TM, NextFnNum++, - getAnalysis<MachineModuleInfo>().getContext()); + getAnalysis<MachineModuleInfo>()); return false; } @@ -46,8 +59,3 @@ void MachineFunctionAnalysis::releaseMemory() { delete MF; MF = 0; } - -void MachineFunctionAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<MachineModuleInfo>(); -} diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index ad4f01b7a9ad..f813a553670b 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -262,6 +262,7 @@ MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI) // Always emit some info, by default "no personality" info. Personalities.push_back(NULL); AddrLabelSymbols = 0; + TheModule = 0; } MachineModuleInfo::MachineModuleInfo() diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index e47ba7c2cc37..e65961901578 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -126,6 +126,11 @@ bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { // Can't sink anything out of a block that has less than two successors. if (MBB.succ_size() <= 1 || MBB.empty()) return false; + // Don't bother sinking code out of unreachable blocks. In addition to being + // unprofitable, it can also lead to infinite looping, because in an unreachable + // loop there may be nowhere to stop. + if (!DT->isReachableFromEntry(&MBB)) return false; + bool MadeChange = false; // Walk the basic block bottom-up. Remember if we saw a store. diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 2d54cd427418..27cb566d9512 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -24,7 +24,6 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Target/TargetMachine.h" @@ -59,11 +58,6 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); FrameConstantRegMap.clear(); - // Get MachineModuleInfo so that we can track the construction of the - // frame. - if (MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>()) - Fn.getFrameInfo()->setMachineModuleInfo(MMI); - // Calculate the MaxCallFrameSize and HasCalls variables for the function's // frame information. Also eliminates call frame pseudo instructions. calculateCallsInformation(Fn); diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index d6f8a205c1f6..4bf41f28c250 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -47,7 +47,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" @@ -326,8 +325,8 @@ bool FastISel::SelectCall(User *I) { default: break; case Intrinsic::dbg_declare: { DbgDeclareInst *DI = cast<DbgDeclareInst>(I); - if (!DIDescriptor::ValidDebugInfo(DI->getVariable(), CodeGenOpt::None)||!DW - || !DW->ShouldEmitDwarfDebug()) + if (!DIDescriptor::ValidDebugInfo(DI->getVariable(), CodeGenOpt::None) || + !MF.getMMI().hasDebugInfo()) return true; Value *Address = DI->getAddress(); @@ -341,7 +340,7 @@ bool FastISel::SelectCall(User *I) { if (SI == StaticAllocaMap.end()) break; // VLAs. int FI = SI->second; if (!DI->getDebugLoc().isUnknown()) - MMI->setVariableDbgInfo(DI->getVariable(), FI, DI->getDebugLoc()); + MF.getMMI().setVariableDbgInfo(DI->getVariable(), FI, DI->getDebugLoc()); // Building the map above is target independent. Generating DBG_VALUE // inline is target dependent; do this now. @@ -400,44 +399,39 @@ bool FastISel::SelectCall(User *I) { switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { default: break; case TargetLowering::Expand: { - if (MMI) { - if (MBB->isLandingPad()) - AddCatchInfo(*cast<CallInst>(I), MMI, MBB); - else { + if (MBB->isLandingPad()) + AddCatchInfo(*cast<CallInst>(I), &MF.getMMI(), MBB); + else { #ifndef NDEBUG - CatchInfoLost.insert(cast<CallInst>(I)); + CatchInfoLost.insert(cast<CallInst>(I)); #endif - // FIXME: Mark exception selector register as live in. Hack for PR1508. - unsigned Reg = TLI.getExceptionSelectorRegister(); - if (Reg) MBB->addLiveIn(Reg); - } - + // FIXME: Mark exception selector register as live in. Hack for PR1508. unsigned Reg = TLI.getExceptionSelectorRegister(); - EVT SrcVT = TLI.getPointerTy(); - const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); - unsigned ResultReg = createResultReg(RC); - bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Reg, - RC, RC); - assert(InsertedCopy && "Can't copy address registers!"); - InsertedCopy = InsertedCopy; - - // Cast the register to the type of the selector. - if (SrcVT.bitsGT(MVT::i32)) - ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, - ResultReg); - else if (SrcVT.bitsLT(MVT::i32)) - ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, - ISD::SIGN_EXTEND, ResultReg); - if (ResultReg == 0) - // Unhandled operand. Halt "fast" selection and bail. - return false; - - UpdateValueMap(I, ResultReg); - } else { - unsigned ResultReg = - getRegForValue(Constant::getNullValue(I->getType())); - UpdateValueMap(I, ResultReg); + if (Reg) MBB->addLiveIn(Reg); } + + unsigned Reg = TLI.getExceptionSelectorRegister(); + EVT SrcVT = TLI.getPointerTy(); + const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); + unsigned ResultReg = createResultReg(RC); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Reg, + RC, RC); + assert(InsertedCopy && "Can't copy address registers!"); + InsertedCopy = InsertedCopy; + + // Cast the register to the type of the selector. + if (SrcVT.bitsGT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, + ResultReg); + else if (SrcVT.bitsLT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, + ISD::SIGN_EXTEND, ResultReg); + if (ResultReg == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + UpdateValueMap(I, ResultReg); + return true; } } @@ -734,8 +728,6 @@ FastISel::SelectOperator(User *I, unsigned Opcode) { } FastISel::FastISel(MachineFunction &mf, - MachineModuleInfo *mmi, - DwarfWriter *dw, DenseMap<const Value *, unsigned> &vm, DenseMap<const BasicBlock *, MachineBasicBlock *> &bm, DenseMap<const AllocaInst *, int> &am @@ -751,8 +743,6 @@ FastISel::FastISel(MachineFunction &mf, CatchInfoLost(cil), #endif MF(mf), - MMI(mmi), - DW(dw), MRI(MF.getRegInfo()), MFI(*MF.getFrameInfo()), MCP(*MF.getConstantPool()), diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 63ca8e67000e..d35f0da393e4 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -16,7 +16,6 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Target/TargetFrameInfo.h" diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3643ea7c5315..8c0554d186d9 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -793,7 +793,7 @@ unsigned SelectionDAG::getEVTAlignment(EVT VT) const { // EntryNode could meaningfully have debug info if we can find it... SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) - : TLI(tli), FLI(fli), DW(0), + : TLI(tli), FLI(fli), EntryNode(ISD::EntryToken, DebugLoc(), getVTList(MVT::Other)), Root(getEntryNode()), Ordering(0) { AllNodes.push_back(&EntryNode); @@ -801,11 +801,8 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) DbgInfo = new SDDbgInfo(); } -void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, - DwarfWriter *dw) { +void SelectionDAG::init(MachineFunction &mf) { MF = &mf; - MMI = mmi; - DW = dw; Context = &mf.getFunction()->getContext(); } @@ -2258,8 +2255,7 @@ bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { if (GA->getOffset() != 0) return false; GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal()); if (!GV) return false; - MachineModuleInfo *MMI = getMachineModuleInfo(); - return MMI && MMI->hasDebugInfo(); + return MF->getMMI().hasDebugInfo(); } @@ -3210,11 +3206,9 @@ static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps, NonScalarIntSafe, DAG); if (VT == MVT::Other) { - VT = TLI.getPointerTy(); - const Type *Ty = VT.getTypeForEVT(*DAG.getContext()); - if (DstAlign >= TLI.getTargetData()->getABITypeAlignment(Ty) || + if (DstAlign >= TLI.getTargetData()->getPointerPrefAlignment() || TLI.allowsUnalignedMemoryAccesses(VT)) { - VT = MVT::i64; + VT = TLI.getPointerTy(); } else { switch (DstAlign & 7) { case 0: VT = MVT::i64; break; @@ -3263,7 +3257,8 @@ static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps, static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, - unsigned Align, bool AlwaysInline, + unsigned Align, bool isVol, + bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { // Turn a memcpy of undef to nop. @@ -3322,7 +3317,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = getMemsetStringVal(VT, dl, DAG, TLI, Str, SrcOff); Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, false, Align); + DstSV, DstSVOff + DstOff, isVol, false, Align); } else { // The type might not be legal for the target. This should only happen // if the type is smaller than a legal type, as on PPC, so the right @@ -3333,11 +3328,11 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, assert(NVT.bitsGE(VT)); Value = DAG.getExtLoad(ISD::EXTLOAD, dl, NVT, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, VT, false, false, + SrcSV, SrcSVOff + SrcOff, VT, isVol, false, MinAlign(SrcAlign, SrcOff)); Store = DAG.getTruncStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, VT, false, false, + DstSV, DstSVOff + DstOff, VT, isVol, false, Align); } OutChains.push_back(Store); @@ -3352,7 +3347,8 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, - unsigned Align,bool AlwaysInline, + unsigned Align, bool isVol, + bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { // Turn a memmove of undef to nop. @@ -3403,7 +3399,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = DAG.getLoad(VT, dl, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, false, false, SrcAlign); + SrcSV, SrcSVOff + SrcOff, isVol, false, SrcAlign); LoadValues.push_back(Value); LoadChains.push_back(Value.getValue(1)); SrcOff += VTSize; @@ -3418,7 +3414,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Store = DAG.getStore(Chain, dl, LoadValues[i], getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, false, Align); + DstSV, DstSVOff + DstOff, isVol, false, Align); OutChains.push_back(Store); DstOff += VTSize; } @@ -3430,7 +3426,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, - unsigned Align, + unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff) { // Turn a memset of undef to nop. if (Src.getOpcode() == ISD::UNDEF) @@ -3472,7 +3468,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue Value = getMemsetValue(Src, VT, DAG, dl); SDValue Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, false, 0); + DstSV, DstSVOff + DstOff, isVol, false, 0); OutChains.push_back(Store); DstOff += VTSize; } @@ -3483,7 +3479,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, - unsigned Align, bool AlwaysInline, + unsigned Align, bool isVol, bool AlwaysInline, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { @@ -3497,7 +3493,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Result = getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(),Align, - false, DstSV, DstSVOff, SrcSV, SrcSVOff); + isVol, false, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; } @@ -3506,7 +3502,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, // code. If the target chooses to do this, this is the next best. SDValue Result = TLI.EmitTargetCodeForMemcpy(*this, dl, Chain, Dst, Src, Size, Align, - AlwaysInline, + isVol, AlwaysInline, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; @@ -3516,10 +3512,16 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, if (AlwaysInline) { assert(ConstantSize && "AlwaysInline requires a constant size!"); return getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, - ConstantSize->getZExtValue(), Align, true, - DstSV, DstSVOff, SrcSV, SrcSVOff); + ConstantSize->getZExtValue(), Align, isVol, + true, DstSV, DstSVOff, SrcSV, SrcSVOff); } + // FIXME: If the memcpy is volatile (isVol), lowering it to a plain libc + // memcpy is not guaranteed to be safe. libc memcpys aren't required to + // respect volatile, so they may do things like read or write memory + // beyond the given memory regions. But fixing this isn't easy, and most + // people don't care. + // Emit a library call. TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; @@ -3541,7 +3543,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, - unsigned Align, + unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff, const Value *SrcSV, uint64_t SrcSVOff) { @@ -3555,8 +3557,8 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Result = getMemmoveLoadsAndStores(*this, dl, Chain, Dst, Src, - ConstantSize->getZExtValue(), - Align, false, DstSV, DstSVOff, SrcSV, SrcSVOff); + ConstantSize->getZExtValue(), Align, isVol, + false, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; } @@ -3564,12 +3566,13 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, // Then check to see if we should lower the memmove with target-specific // code. If the target chooses to do this, this is the next best. SDValue Result = - TLI.EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size, Align, + TLI.EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size, Align, isVol, DstSV, DstSVOff, SrcSV, SrcSVOff); if (Result.getNode()) return Result; // Emit a library call. + assert(!isVol && "library memmove does not support volatile"); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Ty = TLI.getTargetData()->getIntPtrType(*getContext()); @@ -3590,7 +3593,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, - unsigned Align, + unsigned Align, bool isVol, const Value *DstSV, uint64_t DstSVOff) { // Check to see if we should lower the memset to stores first. @@ -3601,9 +3604,10 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, if (ConstantSize->isNullValue()) return Chain; - SDValue Result = getMemsetStores(*this, dl, Chain, Dst, Src, - ConstantSize->getZExtValue(), - Align, DstSV, DstSVOff); + SDValue Result = + getMemsetStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), + Align, isVol, DstSV, DstSVOff); + if (Result.getNode()) return Result; } @@ -3611,12 +3615,13 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, // Then check to see if we should lower the memset with target-specific // code. If the target chooses to do this, this is the next best. SDValue Result = - TLI.EmitTargetCodeForMemset(*this, dl, Chain, Dst, Src, Size, Align, + TLI.EmitTargetCodeForMemset(*this, dl, Chain, Dst, Src, Size, Align, isVol, DstSV, DstSVOff); if (Result.getNode()) return Result; // Emit a library call. + assert(!isVol && "library memset does not support volatile"); const Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 879bdb2cbbb7..4bbb3dea92f4 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -40,7 +40,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" @@ -3731,28 +3730,50 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::longjmp: return "_longjmp"+!TLI.usesUnderscoreLongJmp(); case Intrinsic::memcpy: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast<PointerType>(I.getOperand(1)->getType())->getAddressSpace() + < 256 && + cast<PointerType>(I.getOperand(2)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); SDValue Op1 = getValue(I.getOperand(1)); SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); - DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, + bool isVol = cast<ConstantInt>(I.getOperand(5))->getZExtValue(); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol, false, I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } case Intrinsic::memset: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast<PointerType>(I.getOperand(1)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); SDValue Op1 = getValue(I.getOperand(1)); SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); - DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, + bool isVol = cast<ConstantInt>(I.getOperand(5))->getZExtValue(); + DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, isVol, I.getOperand(1), 0)); return 0; } case Intrinsic::memmove: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast<PointerType>(I.getOperand(1)->getType())->getAddressSpace() + < 256 && + cast<PointerType>(I.getOperand(2)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); SDValue Op1 = getValue(I.getOperand(1)); SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); + bool isVol = cast<ConstantInt>(I.getOperand(5))->getZExtValue(); // If the source and destination are known to not be aliases, we can // lower memmove as memcpy. @@ -3761,12 +3782,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Size = C->getZExtValue(); if (AA->alias(I.getOperand(1), Size, I.getOperand(2), Size) == AliasAnalysis::NoAlias) { - DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, - I.getOperand(1), 0, I.getOperand(2), 0)); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol, + false, I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } - DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, + DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, isVol, I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } @@ -3776,9 +3797,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { if (OptLevel != CodeGenOpt::None) // FIXME: Variable debug info is not supported here. return 0; - DwarfWriter *DW = DAG.getDwarfWriter(); - if (!DW) - return 0; DbgDeclareInst &DI = cast<DbgDeclareInst>(I); if (!DIDescriptor::ValidDebugInfo(DI.getVariable(), CodeGenOpt::None)) return 0; @@ -3799,15 +3817,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; // VLAs. int FI = SI->second; - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) - if (!DI.getDebugLoc().isUnknown()) - MMI->setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo()) + MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); return 0; } case Intrinsic::dbg_value: { - DwarfWriter *DW = DAG.getDwarfWriter(); - if (!DW) - return 0; DbgValueInst &DI = cast<DbgValueInst>(I); if (!DIDescriptor::ValidDebugInfo(DI.getVariable(), CodeGenOpt::None)) return 0; @@ -3852,9 +3867,9 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; // VLAs. int FI = SI->second; - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) - if (!DI.getDebugLoc().isUnknown()) - MMI->setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo()) + MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); return 0; } case Intrinsic::eh_exception: { @@ -3870,10 +3885,9 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::eh_selector: { - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); - + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); if (CurMBB->isLandingPad()) - AddCatchInfo(I, MMI, CurMBB); + AddCatchInfo(I, &MMI, CurMBB); else { #ifndef NDEBUG FuncInfo.CatchInfoLost.insert(&I); @@ -3895,40 +3909,25 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::eh_typeid_for: { - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); - - if (MMI) { - // Find the type id for the given typeinfo. - GlobalVariable *GV = ExtractTypeInfo(I.getOperand(1)); - unsigned TypeID = MMI->getTypeIDFor(GV); - Res = DAG.getConstant(TypeID, MVT::i32); - } else { - // Return something different to eh_selector. - Res = DAG.getConstant(1, MVT::i32); - } - + // Find the type id for the given typeinfo. + GlobalVariable *GV = ExtractTypeInfo(I.getOperand(1)); + unsigned TypeID = DAG.getMachineFunction().getMMI().getTypeIDFor(GV); + Res = DAG.getConstant(TypeID, MVT::i32); setValue(&I, Res); return 0; } case Intrinsic::eh_return_i32: case Intrinsic::eh_return_i64: - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { - MMI->setCallsEHReturn(true); - DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, - MVT::Other, - getControlRoot(), - getValue(I.getOperand(1)), - getValue(I.getOperand(2)))); - } else { - setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); - } - + DAG.getMachineFunction().getMMI().setCallsEHReturn(true); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, + MVT::Other, + getControlRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); return 0; case Intrinsic::eh_unwind_init: - if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { - MMI->setCallsUnwindInit(true); - } + DAG.getMachineFunction().getMMI().setCallsUnwindInit(true); return 0; case Intrinsic::eh_dwarf_cfa: { EVT VT = getValue(I.getOperand(1)).getValueType(); @@ -3947,12 +3946,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; } case Intrinsic::eh_sjlj_callsite: { - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1)); assert(CI && "Non-constant call site value in eh.sjlj.callsite!"); - assert(MMI->getCurrentCallSite() == 0 && "Overlapping call sites!"); + assert(MMI.getCurrentCallSite() == 0 && "Overlapping call sites!"); - MMI->setCurrentCallSite(CI->getZExtValue()); + MMI.setCurrentCallSite(CI->getZExtValue()); return 0; } @@ -4337,7 +4336,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, const PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType()); const FunctionType *FTy = cast<FunctionType>(PT->getElementType()); const Type *RetTy = FTy->getReturnType(); - MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); MCSymbol *BeginLabel = 0; TargetLowering::ArgListTy Args; @@ -4395,18 +4394,18 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, Args.push_back(Entry); } - if (LandingPad && MMI) { + if (LandingPad) { // Insert a label before the invoke call to mark the try range. This can be // used to detect deletion of the invoke via the MachineModuleInfo. - BeginLabel = MMI->getContext().CreateTempSymbol(); + BeginLabel = MMI.getContext().CreateTempSymbol(); // For SjLj, keep track of which landing pads go with which invokes // so as to maintain the ordering of pads in the LSDA. - unsigned CallSiteIndex = MMI->getCurrentCallSite(); + unsigned CallSiteIndex = MMI.getCurrentCallSite(); if (CallSiteIndex) { - MMI->setCallSiteBeginLabel(BeginLabel, CallSiteIndex); + MMI.setCallSiteBeginLabel(BeginLabel, CallSiteIndex); // Now that the call site is handled, stop tracking it. - MMI->setCurrentCallSite(0); + MMI.setCurrentCallSite(0); } // Both PendingLoads and PendingExports must be flushed here; @@ -4497,14 +4496,14 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, else HasTailCall = true; - if (LandingPad && MMI) { + if (LandingPad) { // Insert a label at the end of the invoke call to mark the try range. This // can be used to detect deletion of the invoke via the MachineModuleInfo. - MCSymbol *EndLabel = MMI->getContext().CreateTempSymbol(); + MCSymbol *EndLabel = MMI.getContext().CreateTempSymbol(); DAG.setRoot(DAG.getEHLabel(getCurDebugLoc(), getRoot(), EndLabel)); // Inform MachineModuleInfo of range. - MMI->addInvoke(LandingPad, BeginLabel, EndLabel); + MMI.addInvoke(LandingPad, BeginLabel, EndLabel); } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 9f027729b75e..fdcba0f0bc72 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -56,7 +56,6 @@ class InsertValueInst; class Instruction; class LoadInst; class MachineBasicBlock; -class MachineFunction; class MachineInstr; class MachineRegisterInfo; class PHINode; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index d54566b8cd3a..9b137a52f7c3 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -41,7 +41,6 @@ #include "llvm/CodeGen/ScheduleHazardRecognizer.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/DwarfWriter.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" @@ -303,8 +302,6 @@ void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved<AliasAnalysis>(); AU.addRequired<GCModuleInfo>(); AU.addPreserved<GCModuleInfo>(); - AU.addRequired<DwarfWriter>(); - AU.addPreserved<DwarfWriter>(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -331,9 +328,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { RegInfo = &MF->getRegInfo(); DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); - MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>(); - DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>(); - CurDAG->init(*MF, MMI, DW); + CurDAG->init(*MF); FuncInfo->set(Fn, *MF, EnableFastISel); SDB->init(GFI, *AA); @@ -342,7 +337,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { // Mark landing pad. FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); - SelectAllBasicBlocks(Fn, *MF, MMI, DW, TII); + SelectAllBasicBlocks(Fn, *MF, TII); // If the first basic block in the function has live ins that need to be // copied into vregs, emit the copies into the top of the block before @@ -844,15 +839,11 @@ void SelectionDAGISel::DoInstructionSelection() { void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, - MachineModuleInfo *MMI, - DwarfWriter *DW, const TargetInstrInfo &TII) { // Initialize the Fast-ISel state, if needed. FastISel *FastIS = 0; if (EnableFastISel) - FastIS = TLI.createFastISel(MF, MMI, DW, - FuncInfo->ValueMap, - FuncInfo->MBBMap, + FastIS = TLI.createFastISel(MF, FuncInfo->ValueMap, FuncInfo->MBBMap, FuncInfo->StaticAllocaMap #ifndef NDEBUG , FuncInfo->CatchInfoLost @@ -888,10 +879,10 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, } } - if (MMI && BB->isLandingPad()) { + if (BB->isLandingPad()) { // Add a label to mark the beginning of the landing pad. Deletion of the // landing pad can thus be detected via the MachineModuleInfo. - MCSymbol *Label = MMI->addLandingPad(BB); + MCSymbol *Label = MF.getMMI().addLandingPad(BB); const TargetInstrDesc &II = TII.get(TargetOpcode::EH_LABEL); BuildMI(BB, SDB->getCurDebugLoc(), II).addSym(Label); @@ -925,7 +916,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, if (I == E) // No catch info found - try to extract some from the successor. - CopyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); + CopyCatchInfo(Br->getSuccessor(0), LLVMBB, &MF.getMMI(), *FuncInfo); } } |