X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FDwarfWriter.cpp;h=784bf930b584db7690734a66ba13d83a43c8323b;hb=6fa1c051dc515b6fd1f9a26ac12fed985469bff5;hp=faebaacfd7d713041f7498fcf244fca541091b64;hpb=06ff4e67c454fbe32c1697dda2d27ec1ae22e32a;p=oota-llvm.git diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp index faebaacfd7d..784bf930b58 100644 --- a/lib/CodeGen/DwarfWriter.cpp +++ b/lib/CodeGen/DwarfWriter.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by James M. Laskey and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -30,7 +30,7 @@ #include "llvm/Support/Mangler.h" #include "llvm/System/Path.h" #include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/MRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetInstrInfo.h" @@ -296,6 +296,7 @@ public: isString, isLabel, isAsIsLabel, + isSectionOffset, isDelta, isEntry, isBlock @@ -504,6 +505,56 @@ public: #endif }; +//===----------------------------------------------------------------------===// +/// DIESectionOffset - A section offset DIE. +// +class DIESectionOffset : public DIEValue { +public: + const DWLabel Label; + const DWLabel Section; + bool IsEH : 1; + bool UseSet : 1; + + DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec, + bool isEH = false, bool useSet = true) + : DIEValue(isSectionOffset), Label(Lab), Section(Sec), + IsEH(isEH), UseSet(useSet) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIESectionOffset *) { return true; } + static bool classof(const DIEValue *D) { return D->Type == isSectionOffset; } + + /// EmitValue - Emit section offset. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of section offset value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const DWLabel &Label, + const DWLabel &Section) { + ID.AddInteger(isSectionOffset); + Label.Profile(ID); + Section.Profile(ID); + // IsEH and UseSet are specific to the Label/Section that we will emit + // the offset for; so Label/Section are enough for uniqueness. + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label, Section); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Off: "; + Label.print(O); + O << "-"; + Section.print(O); + O << "-" << IsEH << "-" << UseSet; + } +#endif +}; + //===----------------------------------------------------------------------===// /// DIEDelta - A simple label difference DIE. /// @@ -782,7 +833,7 @@ protected: const TargetData *TD; /// RI - Register Information. - const MRegisterInfo *RI; + const TargetRegisterInfo *RI; /// M - Current module. /// @@ -925,19 +976,20 @@ public: void EmitSectionOffset(const char* Label, const char* Section, unsigned LabelNumber, unsigned SectionNumber, - bool IsSmall = false, bool isEH = false) { + bool IsSmall = false, bool isEH = false, + bool useSet = true) { bool printAbsolute = false; - if (TAI->needsSet()) { + if (isEH) + printAbsolute = TAI->isAbsoluteEHSectionOffsets(); + else + printAbsolute = TAI->isAbsoluteDebugSectionOffsets(); + + if (TAI->needsSet() && useSet) { O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; PrintLabelName(Label, LabelNumber); - if (isEH) - printAbsolute = TAI->isAbsoluteEHSectionOffsets(); - else - printAbsolute = TAI->isAbsoluteDebugSectionOffsets(); - if (!printAbsolute) { O << "-"; PrintLabelName(Section, SectionNumber); @@ -953,11 +1005,6 @@ public: PrintLabelName(Label, LabelNumber); - if (isEH) - printAbsolute = TAI->isAbsoluteEHSectionOffsets(); - else - printAbsolute = TAI->isAbsoluteDebugSectionOffsets(); - if (!printAbsolute) { O << "-"; PrintLabelName(Section, SectionNumber); @@ -968,7 +1015,7 @@ public: /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, - const std::vector &Moves) { + const std::vector &Moves, bool isEH) { int stackGrowth = Asm->TM.getFrameInfo()->getStackGrowthDirection() == TargetFrameInfo::StackGrowsUp ? @@ -1010,7 +1057,7 @@ public: } else { Asm->EmitInt8(DW_CFA_def_cfa); Asm->EOL("DW_CFA_def_cfa"); - Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister())); + Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister(), isEH)); Asm->EOL("Register"); } @@ -1026,13 +1073,13 @@ public: if (Dst.isRegister()) { Asm->EmitInt8(DW_CFA_def_cfa_register); Asm->EOL("DW_CFA_def_cfa_register"); - Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getRegister())); + Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getRegister(), isEH)); Asm->EOL("Register"); } else { assert(0 && "Machine move no supported yet."); } } else { - unsigned Reg = RI->getDwarfRegNum(Src.getRegister()); + unsigned Reg = RI->getDwarfRegNum(Src.getRegister(), isEH); int Offset = Dst.getOffset() / stackGrowth; if (Offset < 0) { @@ -1279,6 +1326,24 @@ public: Die->AddValue(Attribute, Form, Value); } + /// AddSectionOffset - Add a section offset label attribute data and value. + /// + void AddSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label, const DWLabel &Section, + bool isEH = false, bool useSet = true) { + FoldingSetNodeID ID; + DIESectionOffset::Profile(ID, Label, Section); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + if (!Value) { + Value = new DIESectionOffset(Label, Section, isEH, useSet); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); + } + /// AddDelta - Add a label delta attribute data and value. /// void AddDelta(DIE *Die, unsigned Attribute, unsigned Form, @@ -1340,7 +1405,7 @@ private: /// provided. void AddAddress(DIE *Die, unsigned Attribute, const MachineLocation &Location) { - unsigned Reg = RI->getDwarfRegNum(Location.getRegister()); + unsigned Reg = RI->getDwarfRegNum(Location.getRegister(), false); DIEBlock *Block = new DIEBlock(); if (Location.isRegister()) { @@ -1718,11 +1783,8 @@ private: CompileUnit *NewCompileUnit(CompileUnitDesc *UnitDesc, unsigned ID) { // Construct debug information entry. DIE *Die = new DIE(DW_TAG_compile_unit); - if (TAI->isAbsoluteDebugSectionOffsets()) - AddLabel(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0)); - else - AddDelta(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0), - DWLabel("section_line", 0)); + AddSectionOffset(Die, DW_AT_stmt_list, DW_FORM_data4, + DWLabel("section_line", 0), DWLabel("section_line", 0), false); AddString(Die, DW_AT_producer, DW_FORM_string, UnitDesc->getProducer()); AddUInt (Die, DW_AT_language, DW_FORM_data1, UnitDesc->getLanguage()); AddString(Die, DW_AT_name, DW_FORM_string, UnitDesc->getFileName()); @@ -1875,7 +1937,8 @@ private: // Add variable address. MachineLocation Location; - RI->getLocation(*MF, DV->getFrameIndex(), Location); + Location.set(RI->getFrameRegister(*MF), + RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); AddAddress(VariableDie, DW_AT_location, Location); return VariableDie; @@ -1971,19 +2034,6 @@ private: if (didInitial) return; didInitial = true; - // Print out .file directives to specify files for .loc directives. - if (TAI->hasDotLocAndDotFile()) { - const UniqueVector &SourceFiles = MMI->getSourceFiles(); - const UniqueVector &Directories = MMI->getDirectories(); - for (unsigned i = 1, e = SourceFiles.size(); i <= e; ++i) { - sys::Path FullPath(Directories[SourceFiles[i].getDirectoryID()]); - bool AppendOk = FullPath.appendComponent(SourceFiles[i].getName()); - assert(AppendOk && "Could not append filename to directory!"); - Asm->EmitFile(i, FullPath.toString()); - Asm->EOL(); - } - } - // Dwarf sections base addresses. if (TAI->doesDwarfRequireFrameSection()) { Asm->SwitchToDataSection(TAI->getDwarfFrameSection()); @@ -2383,15 +2433,15 @@ private: Asm->EOL("CIE Code Alignment Factor"); Asm->EmitSLEB128Bytes(stackGrowth); Asm->EOL("CIE Data Alignment Factor"); - Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister())); + Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); Asm->EOL("CIE RA Column"); std::vector Moves; RI->getInitialFrameState(Moves); - EmitFrameMoves(NULL, 0, Moves); + EmitFrameMoves(NULL, 0, Moves, false); - Asm->EmitAlignment(2); + Asm->EmitAlignment(2, 0, 0, false); EmitLabel("debug_frame_common_end", 0); Asm->EOL(); @@ -2422,9 +2472,9 @@ private: "func_begin", DebugFrameInfo.Number); Asm->EOL("FDE address range"); - EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves); + EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, false); - Asm->EmitAlignment(2); + Asm->EmitAlignment(2, 0, 0, false); EmitLabel("debug_frame_end", DebugFrameInfo.Number); Asm->EOL(); @@ -2626,9 +2676,6 @@ public: MMI = mmi; shouldEmit = true; - // Emit initial sections - EmitInitial(); - // Create all the compile unit DIEs. ConstructCompileUnitDIEs(); @@ -2640,6 +2687,23 @@ public: // Prime section data. SectionMap.insert(TAI->getTextSection()); + + // Print out .file directives to specify files for .loc directives. These + // are printed out early so that they precede any .loc directives. + if (TAI->hasDotLocAndDotFile()) { + const UniqueVector &SourceFiles = MMI->getSourceFiles(); + const UniqueVector &Directories = MMI->getDirectories(); + for (unsigned i = 1, e = SourceFiles.size(); i <= e; ++i) { + sys::Path FullPath(Directories[SourceFiles[i].getDirectoryID()]); + bool AppendOk = FullPath.appendComponent(SourceFiles[i].getName()); + assert(AppendOk && "Could not append filename to directory!"); + Asm->EmitFile(i, FullPath.toString()); + Asm->EOL(); + } + } + + // Emit initial sections + EmitInitial(); } } @@ -2719,6 +2783,14 @@ public: // Assumes in correct section after the entry point. EmitLabel("func_begin", ++SubprogramCount); + + // Emit label for the implicitly defined dbg.stoppoint at the start of + // the function. + const std::vector &LineInfos = MMI->getSourceLines(); + if (!LineInfos.empty()) { + const SourceLineInfo &LineInfo = LineInfos[0]; + Asm->printLabel(LineInfo.getLabelID()); + } } /// EndFunction - Gather and emit post-function debug information. @@ -2763,20 +2835,34 @@ private: bool hasCalls; bool hasLandingPads; std::vector Moves; + const Function * function; FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P, bool hC, bool hL, - const std::vector &M): + const std::vector &M, + const Function *f): FnName(FN), Number(Num), PersonalityIndex(P), - hasCalls(hC), hasLandingPads(hL), Moves(M) { } + hasCalls(hC), hasLandingPads(hL), Moves(M), function (f) { } }; std::vector EHFrames; - - /// shouldEmit - Flag to indicate if debug information should be emitted. - /// - bool shouldEmit; - + + /// shouldEmitTable - Per-function flag to indicate if EH tables should + /// be emitted. + bool shouldEmitTable; + + /// shouldEmitMoves - Per-function flag to indicate if frame moves info + /// should be emitted. + bool shouldEmitMoves; + + /// shouldEmitTableModule - Per-module flag to indicate if EH tables + /// should be emitted. + bool shouldEmitTableModule; + + /// shouldEmitFrameModule - Per-module flag to indicate if frame moves + /// should be emitted. + bool shouldEmitMovesModule; + /// EmitCommonEHFrame - Emit the common eh unwind frame. /// void EmitCommonEHFrame(const Function *Personality, unsigned Index) { @@ -2793,7 +2879,7 @@ private: // Define base labels. EmitLabel("eh_frame_common", Index); - + // Define the eh frame length. EmitDifference("eh_frame_common_end", Index, "eh_frame_common_begin", Index, true); @@ -2805,76 +2891,109 @@ private: Asm->EOL("CIE Identifier Tag"); Asm->EmitInt8(DW_CIE_VERSION); Asm->EOL("CIE Version"); - + // The personality presence indicates that language specific information // will show up in the eh frame. Asm->EmitString(Personality ? "zPLR" : "zR"); Asm->EOL("CIE Augmentation"); - + // Round out reader. Asm->EmitULEB128Bytes(1); Asm->EOL("CIE Code Alignment Factor"); Asm->EmitSLEB128Bytes(stackGrowth); - Asm->EOL("CIE Data Alignment Factor"); - Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister())); - Asm->EOL("CIE RA Column"); - + Asm->EOL("CIE Data Alignment Factor"); + Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); + Asm->EOL("CIE Return Address Column"); + // If there is a personality, we need to indicate the functions location. if (Personality) { Asm->EmitULEB128Bytes(7); Asm->EOL("Augmentation Size"); - if (TAI->getNeedsIndirectEncoding()) + if (TAI->getNeedsIndirectEncoding()) { Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect); - else + Asm->EOL("Personality (pcrel sdata4 indirect)"); + } else { Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); + Asm->EOL("Personality (pcrel sdata4)"); + } - Asm->EOL("Personality (pcrel sdata4 indirect)"); - - PrintRelDirective(); + PrintRelDirective(true); O << TAI->getPersonalityPrefix(); Asm->EmitExternalGlobal((const GlobalVariable *)(Personality)); O << TAI->getPersonalitySuffix(); - O << "-" << TAI->getPCSymbol(); + if (strcmp(TAI->getPersonalitySuffix(), "+4@GOTPCREL")) + O << "-" << TAI->getPCSymbol(); Asm->EOL("Personality"); - Asm->EmitULEB128Bytes(DW_EH_PE_pcrel); - Asm->EOL("LSDA Encoding (pcrel)"); - Asm->EmitULEB128Bytes(DW_EH_PE_pcrel); - Asm->EOL("FDE Encoding (pcrel)"); + Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); + Asm->EOL("LSDA Encoding (pcrel sdata4)"); + Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); + Asm->EOL("FDE Encoding (pcrel sdata4)"); } else { Asm->EmitULEB128Bytes(1); Asm->EOL("Augmentation Size"); - Asm->EmitULEB128Bytes(DW_EH_PE_pcrel); - Asm->EOL("FDE Encoding (pcrel)"); + Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); + Asm->EOL("FDE Encoding (pcrel sdata4)"); } // Indicate locations of general callee saved registers in frame. std::vector Moves; RI->getInitialFrameState(Moves); - EmitFrameMoves(NULL, 0, Moves); + EmitFrameMoves(NULL, 0, Moves, true); - Asm->EmitAlignment(2); + // 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, + 0, 0, false); EmitLabel("eh_frame_common_end", Index); - + Asm->EOL(); } - + /// EmitEHFrame - Emit function exception frame information. /// void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { + Function::LinkageTypes linkage = EHFrameInfo.function->getLinkage(); + Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection()); // Externally visible entry into the functions eh frame info. - if (const char *GlobalDirective = TAI->getGlobalDirective()) - O << GlobalDirective << EHFrameInfo.FnName << "\n"; - - // If there are no calls then you can't unwind. - if (!EHFrameInfo.hasCalls) { + // If the corresponding function is static, this should not be + // externally visible. + if (linkage != Function::InternalLinkage) { + if (const char *GlobalEHDirective = TAI->getGlobalEHDirective()) + O << GlobalEHDirective << EHFrameInfo.FnName << "\n"; + } + + // If corresponding function is weak definition, this should be too. + if ((linkage == Function::WeakLinkage || + linkage == Function::LinkOnceLinkage) && + TAI->getWeakDefDirective()) + O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; + + // If there are no calls then you can't unwind. This may mean we can + // omit the EH Frame, but some environments do not handle weak absolute + // symbols. + // If UnwindTablesMandatory is set we cannot do this optimization; the + // unwind info is to be available for non-EH uses. + if (!EHFrameInfo.hasCalls && + !UnwindTablesMandatory && + ((linkage != Function::WeakLinkage && + linkage != Function::LinkOnceLinkage) || + !TAI->getWeakDefDirective() || + TAI->getSupportsWeakOmittedEHFrame())) + { O << EHFrameInfo.FnName << " = 0\n"; + // 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 (const char *UsedDirective = TAI->getUsedDirective()) + O << UsedDirective << EHFrameInfo.FnName << "\n\n"; } else { O << EHFrameInfo.FnName << ":\n"; - + // EH frame header. EmitDifference("eh_frame_end", EHFrameInfo.Number, "eh_frame_begin", EHFrameInfo.Number, true); @@ -2884,44 +3003,51 @@ private: EmitSectionOffset("eh_frame_begin", "eh_frame_common", EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, - true, true); + true, true, false); Asm->EOL("FDE CIE offset"); - EmitReference("eh_func_begin", EHFrameInfo.Number, true); + EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); Asm->EOL("FDE initial location"); EmitDifference("eh_func_end", EHFrameInfo.Number, - "eh_func_begin", EHFrameInfo.Number); + "eh_func_begin", EHFrameInfo.Number, true); Asm->EOL("FDE address range"); - + // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (EHFrameInfo.PersonalityIndex) { Asm->EmitULEB128Bytes(4); Asm->EOL("Augmentation size"); - - if (EHFrameInfo.hasLandingPads) { - EmitReference("exception", EHFrameInfo.Number, true); - } else if (TD->getPointerSize() == 8) { - Asm->EmitInt64((int)0); - } else { + + if (EHFrameInfo.hasLandingPads) + EmitReference("exception", EHFrameInfo.Number, true, true); + else Asm->EmitInt32((int)0); - } Asm->EOL("Language Specific Data Area"); } else { Asm->EmitULEB128Bytes(0); Asm->EOL("Augmentation size"); } - + // Indicate locations of function specific callee saved registers in // frame. - EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves); + EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, true); - Asm->EmitAlignment(2); + // 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, + 0, 0, false); EmitLabel("eh_frame_end", EHFrameInfo.Number); - } - if (const char *UsedDirective = TAI->getUsedDirective()) - O << UsedDirective << EHFrameInfo.FnName << "\n\n"; + // 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 retains the function in this case, and there is code around + // that depends on unused functions (calling undefined externals) being + // dead-stripped to link correctly. Yes, there really is. + if (MMI->getUsedFunctions().count(EHFrameInfo.function)) + if (const char *UsedDirective = TAI->getUsedDirective()) + O << UsedDirective << EHFrameInfo.FnName << "\n\n"; + } } /// EmitExceptionTable - Emit landing pads and actions. @@ -2999,16 +3125,15 @@ private: /// CallSiteEntry - Structure describing an entry in the call-site table. struct CallSiteEntry { + // The 'try-range' is BeginLabel .. EndLabel. unsigned BeginLabel; // zero indicates the start of the function. unsigned EndLabel; // zero indicates the end of the function. + // The landing pad starts at PadLabel. unsigned PadLabel; // zero indicates that there is no landing pad. unsigned Action; }; void EmitExceptionTable() { - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(); - const std::vector &TypeInfos = MMI->getTypeInfos(); const std::vector &FilterIds = MMI->getFilterIds(); const std::vector &PadInfos = MMI->getLandingPads(); @@ -3099,13 +3224,21 @@ private: SizeActions += SizeSiteActions; } - // Compute the call-site table. Entries must be ordered by address. + // Compute the call-site table. The entry for an invoke has a try-range + // containing the call, a non-zero landing pad and an appropriate action. + // The entry for an ordinary call has a try-range containing the call and + // zero for the landing pad and the action. Calls marked 'nounwind' have + // no entry and must not be contained in the try-range of any entry - they + // form gaps in the table. Entries must be ordered by try-range address. SmallVector CallSites; RangeMapType PadMap; + // Invokes and nounwind calls have entries in PadMap (due to being bracketed + // by try-range labels when lowered). Ordinary calls do not, so appropriate + // try-ranges for them need be deduced. for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LandingPad = LandingPads[i]; - for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { unsigned BeginLabel = LandingPad->BeginLabels[j]; assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); PadRange P = { i, j }; @@ -3113,27 +3246,37 @@ private: } } - bool MayThrow = false; + // The end label of the previous invoke or nounwind try-range. unsigned LastLabel = 0; - const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + // Whether there is a potentially throwing instruction (currently this means + // an ordinary call) between the end of the previous try-range and now. + bool SawPotentiallyThrowing = false; + + // Whether the last callsite entry was for an invoke. + bool PreviousIsInvoke = false; + + // Visit all instructions in order of address. for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { if (MI->getOpcode() != TargetInstrInfo::LABEL) { - MayThrow |= TII->isCall(MI->getOpcode()); + SawPotentiallyThrowing |= MI->getDesc().isCall(); continue; } - unsigned BeginLabel = MI->getOperand(0).getImmedValue(); + unsigned BeginLabel = MI->getOperand(0).getImm(); assert(BeginLabel && "Invalid label!"); + // End of the previous try-range? if (BeginLabel == LastLabel) - MayThrow = false; + SawPotentiallyThrowing = false; + // Beginning of a new try-range? RangeMapType::iterator L = PadMap.find(BeginLabel); - if (L == PadMap.end()) + // Nope, it was just some random label. continue; PadRange P = L->second; @@ -3145,48 +3288,62 @@ private: // If some instruction between the previous try-range and this one may // throw, create a call-site entry with no landing pad for the region // between the try-ranges. - if (MayThrow) { + if (SawPotentiallyThrowing) { CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; CallSites.push_back(Site); + PreviousIsInvoke = false; } LastLabel = LandingPad->EndLabels[P.RangeIndex]; - CallSiteEntry Site = {BeginLabel, LastLabel, - LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; - - assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && - "Invalid landing pad!"); - - // Try to merge with the previous call-site. - if (CallSites.size()) { - CallSiteEntry &Prev = CallSites[CallSites.size()-1]; - if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { - // Extend the range of the previous entry. - Prev.EndLabel = Site.EndLabel; - continue; + assert(BeginLabel && LastLabel && "Invalid landing pad!"); + + if (LandingPad->LandingPadLabel) { + // This try-range is for an invoke. + CallSiteEntry Site = {BeginLabel, LastLabel, + LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; + + // Try to merge with the previous call-site. + if (PreviousIsInvoke) { + CallSiteEntry &Prev = CallSites[CallSites.size()-1]; + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } } - } - // Otherwise, create a new call-site. - CallSites.push_back(Site); + // Otherwise, create a new call-site. + CallSites.push_back(Site); + PreviousIsInvoke = true; + } else { + // Create a gap. + PreviousIsInvoke = false; + } } } // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. - if (MayThrow) { + if (SawPotentiallyThrowing) { CallSiteEntry Site = {LastLabel, 0, 0, 0}; CallSites.push_back(Site); } // Final tallies. - unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start. - sizeof(int32_t) + // Site length. - sizeof(int32_t)); // Landing pad. + + // Call sites. + const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4 + const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4 + const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4 + unsigned SizeSites = CallSites.size() * (SiteStartSize + + SiteLengthSize + + LandingPadSize); for (unsigned i = 0, e = CallSites.size(); i < e; ++i) SizeSites += Asm->SizeULEB128(CallSites[i].Action); - unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize(); + // Type infos. + const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr + unsigned SizeTypes = TypeInfos.size() * TypeInfoSize; unsigned TypeOffset = sizeof(int8_t) + // Call site format Asm->SizeULEB128(SizeSites) + // Call-site table length @@ -3202,7 +3359,7 @@ private: // Begin the exception table. Asm->SwitchToDataSection(TAI->getDwarfExceptionSection()); O << "GCC_except_table" << SubprogramCount << ":\n"; - Asm->EmitAlignment(2); + Asm->EmitAlignment(2, 0, 0, false); for (unsigned i = 0; i != SizeAlign; ++i) { Asm->EmitInt8(0); Asm->EOL("Padding"); @@ -3236,25 +3393,22 @@ private: } EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, - false, true); + true, true); Asm->EOL("Region start"); if (!S.EndLabel) { - EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber); + EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, + true); } else { - EmitDifference("label", S.EndLabel, BeginTag, BeginNumber); + EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); } Asm->EOL("Region length"); - if (!S.PadLabel) { - if (TD->getPointerSize() == sizeof(int32_t)) - Asm->EmitInt32(0); - else - Asm->EmitInt64(0); - } else { + if (!S.PadLabel) + Asm->EmitInt32(0); + else EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, - false, true); - } + true, true); Asm->EOL("Landing pad"); Asm->EmitULEB128Bytes(S.Action); @@ -3292,7 +3446,7 @@ private: Asm->EOL("Filter TypeInfo index"); } - Asm->EmitAlignment(2); + Asm->EmitAlignment(2, 0, 0, false); } public: @@ -3301,7 +3455,10 @@ public: // DwarfException(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) : Dwarf(OS, A, T, "eh") - , shouldEmit(false) + , shouldEmitTable(false) + , shouldEmitMoves(false) + , shouldEmitTableModule(false) + , shouldEmitMovesModule(false) {} virtual ~DwarfException() {} @@ -3321,47 +3478,61 @@ public: /// EndModule - Emit all exception information that should come after the /// content. void EndModule() { - if (!shouldEmit) return; - - const std::vector Personalities = MMI->getPersonalities(); - for (unsigned i =0; i < Personalities.size(); ++i) - EmitCommonEHFrame(Personalities[i], i); - - for (std::vector::iterator I = EHFrames.begin(), - E = EHFrames.end(); I != E; ++I) - EmitEHFrame(*I); + if (shouldEmitMovesModule || shouldEmitTableModule) { + const std::vector Personalities = MMI->getPersonalities(); + for (unsigned i =0; i < Personalities.size(); ++i) + EmitCommonEHFrame(Personalities[i], i); + + for (std::vector::iterator I = EHFrames.begin(), + E = EHFrames.end(); I != E; ++I) + EmitEHFrame(*I); + } } /// BeginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. void BeginFunction(MachineFunction *MF) { this->MF = MF; - - if (MMI && - ExceptionHandling && - TAI->doesSupportExceptionHandling()) { - shouldEmit = true; - // Assumes in correct section after the entry point. - EmitLabel("eh_func_begin", ++SubprogramCount); + shouldEmitTable = shouldEmitMoves = false; + if (MMI && TAI->doesSupportExceptionHandling()) { + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + // If any landing pads survive, we need an EH table. + if (MMI->getLandingPads().size()) + shouldEmitTable = true; + + // See if we need frame move info. + if (MMI->hasDebugInfo() || + !MF->getFunction()->doesNotThrow() || + UnwindTablesMandatory) + shouldEmitMoves = true; + + if (shouldEmitMoves || shouldEmitTable) + // Assumes in correct section after the entry point. + EmitLabel("eh_func_begin", ++SubprogramCount); } + shouldEmitTableModule |= shouldEmitTable; + shouldEmitMovesModule |= shouldEmitMoves; } /// EndFunction - Gather and emit post-function exception information. /// void EndFunction() { - if (!shouldEmit) return; + if (shouldEmitMoves || shouldEmitTable) { + EmitLabel("eh_func_end", SubprogramCount); + EmitExceptionTable(); - EmitLabel("eh_func_end", SubprogramCount); - EmitExceptionTable(); - - // Save EH frame information - EHFrames. - push_back(FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), + // Save EH frame information + EHFrames. + push_back(FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), SubprogramCount, MMI->getPersonalityIndex(), MF->getFrameInfo()->hasCalls(), !MMI->getLandingPads().empty(), - MMI->getFrameMoves())); + MMI->getFrameMoves(), + MF->getFunction())); + } } }; @@ -3481,12 +3652,14 @@ void DIEString::EmitValue(DwarfDebug &DD, unsigned Form) { /// EmitValue - Emit label value. /// void DIEDwarfLabel::EmitValue(DwarfDebug &DD, unsigned Form) { - DD.EmitReference(Label, false, Form == DW_FORM_data4); + bool IsSmall = Form == DW_FORM_data4; + DD.EmitReference(Label, false, IsSmall); } /// SizeOf - Determine size of label value in bytes. /// unsigned DIEDwarfLabel::SizeOf(const DwarfDebug &DD, unsigned Form) const { + if (Form == DW_FORM_data4) return 4; return DD.getTargetData()->getPointerSize(); } @@ -3495,12 +3668,31 @@ unsigned DIEDwarfLabel::SizeOf(const DwarfDebug &DD, unsigned Form) const { /// EmitValue - Emit label value. /// void DIEObjectLabel::EmitValue(DwarfDebug &DD, unsigned Form) { - DD.EmitReference(Label, false, Form == DW_FORM_data4); + bool IsSmall = Form == DW_FORM_data4; + DD.EmitReference(Label, false, IsSmall); } /// SizeOf - Determine size of label value in bytes. /// unsigned DIEObjectLabel::SizeOf(const DwarfDebug &DD, unsigned Form) const { + if (Form == DW_FORM_data4) return 4; + return DD.getTargetData()->getPointerSize(); +} + +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit delta value. +/// +void DIESectionOffset::EmitValue(DwarfDebug &DD, unsigned Form) { + bool IsSmall = Form == DW_FORM_data4; + DD.EmitSectionOffset(Label.Tag, Section.Tag, + Label.Number, Section.Number, IsSmall, IsEH, UseSet); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIESectionOffset::SizeOf(const DwarfDebug &DD, unsigned Form) const { + if (Form == DW_FORM_data4) return 4; return DD.getTargetData()->getPointerSize(); }