diff options
23 files changed, 1099 insertions, 162 deletions
diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h index 7f46406c478..dc9057521e7 100644 --- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -425,6 +425,7 @@ struct MachineFrameInfo {    StringValue StackProtector;    // TODO: Serialize FunctionContextIdx    unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet. +  unsigned CVBytesOfCalleeSavedRegisters = 0;    bool HasOpaqueSPAdjustment = false;    bool HasVAStart = false;    bool HasMustTailInVarArgFunc = false; @@ -443,6 +444,8 @@ struct MachineFrameInfo {             AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&             StackProtector == Other.StackProtector &&             MaxCallFrameSize == Other.MaxCallFrameSize && +           CVBytesOfCalleeSavedRegisters == +               Other.CVBytesOfCalleeSavedRegisters &&             HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&             HasVAStart == Other.HasVAStart &&             HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc && @@ -465,6 +468,8 @@ template <> struct MappingTraits<MachineFrameInfo> {      YamlIO.mapOptional("stackProtector", MFI.StackProtector,                         StringValue()); // Don't print it out when it's empty.      YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0); +    YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters", +                       MFI.CVBytesOfCalleeSavedRegisters, 0U);      YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,                         false);      YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 2d6081f3577..02b2f1be648 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -266,6 +266,10 @@ private:    /// It is only valid during and after prolog/epilog code insertion.    unsigned MaxCallFrameSize = ~0u; +  /// The number of bytes of callee saved registers that the target wants to +  /// report for the current function in the CodeView S_FRAMEPROC record. +  unsigned CVBytesOfCalleeSavedRegisters = 0; +    /// The prolog/epilog code inserter fills in this vector with each    /// callee saved register saved in the frame.  Beyond its use by the prolog/    /// epilog code inserter, this data used for debug info and exception @@ -603,6 +607,15 @@ public:    }    void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } +  /// Returns how many bytes of callee-saved registers the target pushed in the +  /// prologue. Only used for debug info. +  unsigned getCVBytesOfCalleeSavedRegisters() const { +    return CVBytesOfCalleeSavedRegisters; +  } +  void setCVBytesOfCalleeSavedRegisters(unsigned S) { +    CVBytesOfCalleeSavedRegisters = S; +  } +    /// Create a new object at a fixed location on the stack.    /// All fixed objects should be created before other objects are created for    /// efficiency. By default, fixed objects are not pointed to by LLVM IR diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index fd2a66551ae..4b96bc14ac1 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -512,6 +512,19 @@ enum class RegisterId : uint16_t {  #undef CV_REGISTER  }; +/// Two-bit value indicating which register is the designated frame pointer +/// register. Appears in the S_FRAMEPROC record flags. +enum class EncodedFramePtrReg : uint8_t { +  None = 0, +  StackPtr = 1, +  FramePtr = 2, +  BasePtr = 3, +}; + +RegisterId decodeFramePtrReg(EncodedFramePtrReg EncodedReg, CPUType CPU); + +EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU); +  /// These values correspond to the THUNK_ORDINAL enumeration.  enum class ThunkOrdinal : uint8_t {    Standard, diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 039d390ed10..bc7571b0a99 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -763,49 +763,19 @@ public:    /// Extract the register this frame uses to refer to local variables.    RegisterId getLocalFramePtrReg(CPUType CPU) const { -    return decodeFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U, CPU); +    return decodeFramePtrReg( +        EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU);    }    /// Extract the register this frame uses to refer to parameters.    RegisterId getParamFramePtrReg(CPUType CPU) const { -    return decodeFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U, CPU); +    return decodeFramePtrReg( +        EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);    }    uint32_t RecordOffset;  private: -  static RegisterId decodeFramePtrReg(uint32_t EncodedReg, CPUType CPU) { -    assert(EncodedReg < 4); -    switch (CPU) { -    // FIXME: Add ARM and AArch64 variants here. -    default: -      break; -    case CPUType::Intel8080: -    case CPUType::Intel8086: -    case CPUType::Intel80286: -    case CPUType::Intel80386: -    case CPUType::Intel80486: -    case CPUType::Pentium: -    case CPUType::PentiumPro: -    case CPUType::Pentium3: -      switch (EncodedReg) { -      case 0: return RegisterId::NONE; -      case 1: return RegisterId::VFRAME; -      case 2: return RegisterId::EBP; -      case 3: return RegisterId::EBX; -      } -      llvm_unreachable("bad encoding"); -    case CPUType::X64: -      switch (EncodedReg) { -      case 0: return RegisterId::NONE; -      case 1: return RegisterId::RSP; -      case 2: return RegisterId::RBP; -      case 3: return RegisterId::R13; -      } -      llvm_unreachable("bad encoding"); -    } -    return RegisterId::NONE; -  }  };  // S_CALLSITEINFO diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index f99b5c20e1c..1c67d765dad 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -31,6 +31,7 @@  #include "llvm/BinaryFormat/Dwarf.h"  #include "llvm/CodeGen/AsmPrinter.h"  #include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/CodeGen/MachineFrameInfo.h"  #include "llvm/CodeGen/MachineFunction.h"  #include "llvm/CodeGen/MachineInstr.h"  #include "llvm/CodeGen/MachineModuleInfo.h" @@ -93,6 +94,21 @@ using namespace llvm::codeview;  static cl::opt<bool> EmitDebugGlobalHashes("emit-codeview-ghash-section",                                             cl::ReallyHidden, cl::init(false)); +static CPUType mapArchToCVCPUType(Triple::ArchType Type) { +  switch (Type) { +  case Triple::ArchType::x86: +    return CPUType::Pentium3; +  case Triple::ArchType::x86_64: +    return CPUType::X64; +  case Triple::ArchType::thumb: +    return CPUType::Thumb; +  case Triple::ArchType::aarch64: +    return CPUType::ARM64; +  default: +    report_fatal_error("target architecture doesn't map to a CodeView CPUType"); +  } +} +  CodeViewDebug::CodeViewDebug(AsmPrinter *AP)      : DebugHandlerBase(AP), OS(*Asm->OutStreamer), TypeTable(Allocator) {    // If module doesn't have named metadata anchors or COFF debug section @@ -102,9 +118,11 @@ CodeViewDebug::CodeViewDebug(AsmPrinter *AP)      Asm = nullptr;      return;    } -    // Tell MMI that we have debug info.    MMI->setDebugInfoAvailability(true); + +  TheCPU = +      mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch());  }  StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { @@ -669,21 +687,6 @@ static Version parseVersion(StringRef Name) {    return V;  } -static CPUType mapArchToCVCPUType(Triple::ArchType Type) { -  switch (Type) { -  case Triple::ArchType::x86: -    return CPUType::Pentium3; -  case Triple::ArchType::x86_64: -    return CPUType::X64; -  case Triple::ArchType::thumb: -    return CPUType::Thumb; -  case Triple::ArchType::aarch64: -    return CPUType::ARM64; -  default: -    report_fatal_error("target architecture doesn't map to a CodeView CPUType"); -  } -} -  void CodeViewDebug::emitCompilerInformation() {    MCContext &Context = MMI->getContext();    MCSymbol *CompilerBegin = Context.createTempSymbol(), @@ -707,9 +710,7 @@ void CodeViewDebug::emitCompilerInformation() {    OS.EmitIntValue(Flags, 4);    OS.AddComment("CPUType"); -  CPUType CPU = -      mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch()); -  OS.EmitIntValue(static_cast<uint64_t>(CPU), 2); +  OS.EmitIntValue(static_cast<uint64_t>(TheCPU), 2);    StringRef CompilerVersion = CU->getProducer();    Version FrontVer = parseVersion(CompilerVersion); @@ -801,7 +802,7 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,    OS.EmitLabel(InlineEnd); -  emitLocalVariableList(Site.InlinedLocals); +  emitLocalVariableList(FI, Site.InlinedLocals);    // Recurse on child inlined call sites before closing the scope.    for (const DILocation *ChildSite : Site.ChildSites) { @@ -970,7 +971,31 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,      emitNullTerminatedSymbolName(OS, FuncName);      OS.EmitLabel(ProcRecordEnd); -    emitLocalVariableList(FI.Locals); +    MCSymbol *FrameProcBegin = MMI->getContext().createTempSymbol(), +             *FrameProcEnd = MMI->getContext().createTempSymbol(); +    OS.AddComment("Record length"); +    OS.emitAbsoluteSymbolDiff(FrameProcEnd, FrameProcBegin, 2); +    OS.EmitLabel(FrameProcBegin); +    OS.AddComment("Record kind: S_FRAMEPROC"); +    OS.EmitIntValue(unsigned(SymbolKind::S_FRAMEPROC), 2); +    // Subtract out the CSR size since MSVC excludes that and we include it. +    OS.AddComment("FrameSize"); +    OS.EmitIntValue(FI.FrameSize - FI.CSRSize, 4); +    OS.AddComment("Padding"); +    OS.EmitIntValue(0, 4); +    OS.AddComment("Offset of padding"); +    OS.EmitIntValue(0, 4); +    OS.AddComment("Bytes of callee saved registers"); +    OS.EmitIntValue(FI.CSRSize, 4); +    OS.AddComment("Exception handler offset"); +    OS.EmitIntValue(0, 4); +    OS.AddComment("Exception handler section"); +    OS.EmitIntValue(0, 2); +    OS.AddComment("Flags (defines frame register)"); +    OS.EmitIntValue(uint32_t(FI.FrameProcOpts), 4); +    OS.EmitLabel(FrameProcEnd); + +    emitLocalVariableList(FI, FI.Locals);      emitLexicalBlockList(FI.ChildBlocks, FI);      // Emit inlined call site information. Only emit functions inlined directly @@ -1215,6 +1240,9 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {  }  void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { +  const TargetSubtargetInfo &TSI = MF->getSubtarget(); +  const TargetRegisterInfo *TRI = TSI.getRegisterInfo(); +  const MachineFrameInfo &MFI = MF->getFrameInfo();    const Function &GV = MF->getFunction();    auto Insertion = FnDebugInfo.insert({&GV, llvm::make_unique<FunctionInfo>()});    assert(Insertion.second && "function already has info"); @@ -1222,6 +1250,64 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {    CurFn->FuncId = NextFuncId++;    CurFn->Begin = Asm->getFunctionBegin(); +  // The S_FRAMEPROC record reports the stack size, and how many bytes of +  // callee-saved registers were used. For targets that don't use a PUSH +  // instruction (AArch64), this will be zero. +  CurFn->CSRSize = MFI.getCVBytesOfCalleeSavedRegisters(); +  CurFn->FrameSize = MFI.getStackSize(); + +  // For this function S_FRAMEPROC record, figure out which codeview register +  // will be the frame pointer. +  CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None; // None. +  CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None; // None. +  if (CurFn->FrameSize > 0) { +    if (!TSI.getFrameLowering()->hasFP(*MF)) { +      CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr; +      CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr; +    } else { +      // If there is an FP, parameters are always relative to it. +      CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr; +      if (TRI->needsStackRealignment(*MF)) { +        // If the stack needs realignment, locals are relative to SP or VFRAME. +        CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr; +      } else { +        // Otherwise, locals are relative to EBP, and we probably have VLAs or +        // other stack adjustments. +        CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr; +      } +    } +  } + +  // Compute other frame procedure options. +  FrameProcedureOptions FPO = FrameProcedureOptions::None; +  if (MFI.hasVarSizedObjects()) +    FPO |= FrameProcedureOptions::HasAlloca; +  if (MF->exposesReturnsTwice()) +    FPO |= FrameProcedureOptions::HasSetJmp; +  // FIXME: Set HasLongJmp if we ever track that info. +  if (MF->hasInlineAsm()) +    FPO |= FrameProcedureOptions::HasInlineAssembly; +  if (GV.hasPersonalityFn()) { +    if (isAsynchronousEHPersonality( +            classifyEHPersonality(GV.getPersonalityFn()))) +      FPO |= FrameProcedureOptions::HasStructuredExceptionHandling; +    else +      FPO |= FrameProcedureOptions::HasExceptionHandling; +  } +  if (GV.hasFnAttribute(Attribute::InlineHint)) +    FPO |= FrameProcedureOptions::MarkedInline; +  if (GV.hasFnAttribute(Attribute::Naked)) +    FPO |= FrameProcedureOptions::Naked; +  if (MFI.hasStackProtectorIndex()) +    FPO |= FrameProcedureOptions::SecurityChecks; +  FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedLocalFramePtrReg) << 14U); +  FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedParamFramePtrReg) << 16U); +  if (Asm->TM.getOptLevel() != CodeGenOpt::None && !GV.optForSize() && +      !GV.hasFnAttribute(Attribute::OptimizeNone)) +    FPO |= FrameProcedureOptions::OptimizedForSpeed; +  // FIXME: Set GuardCfg when it is implemented. +  CurFn->FrameProcOpts = FPO; +    OS.EmitCVFuncIdDirective(CurFn->FuncId);    // Find the end of the function prolog.  First known non-DBG_VALUE and @@ -2347,7 +2433,8 @@ void CodeViewDebug::emitDeferredCompleteTypes() {    }  } -void CodeViewDebug::emitLocalVariableList(ArrayRef<LocalVariable> Locals) { +void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI, +                                          ArrayRef<LocalVariable> Locals) {    // Get the sorted list of parameters and emit them first.    SmallVector<const LocalVariable *, 6> Params;    for (const LocalVariable &L : Locals) @@ -2357,15 +2444,16 @@ void CodeViewDebug::emitLocalVariableList(ArrayRef<LocalVariable> Locals) {      return L->DIVar->getArg() < R->DIVar->getArg();    });    for (const LocalVariable *L : Params) -    emitLocalVariable(*L); +    emitLocalVariable(FI, *L);    // Next emit all non-parameters in the order that we found them.    for (const LocalVariable &L : Locals)      if (!L.DIVar->isParameter()) -      emitLocalVariable(L); +      emitLocalVariable(FI, L);  } -void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) { +void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, +                                      const LocalVariable &Var) {    // LocalSym record, see SymbolRecord.h for more info.    MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(),             *LocalEnd = MMI->getContext().createTempSymbol(); @@ -2400,21 +2488,49 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {    for (const LocalVarDefRange &DefRange : Var.DefRanges) {      BytePrefix.clear();      if (DefRange.InMemory) { -      uint16_t RegRelFlags = 0; -      if (DefRange.IsSubfield) { -        RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag | -                      (DefRange.StructOffset -                       << DefRangeRegisterRelSym::OffsetInParentShift); +      int Offset = DefRange.DataOffset; +      unsigned Reg = DefRange.CVRegister; + +      // x86 call sequences often use PUSH instructions, which disrupt +      // ESP-relative offsets. Use the virtual frame pointer, VFRAME or $T0, +      // instead. In simple cases, $T0 will be the CFA. If the frame required +      // re-alignment, it will be the CFA aligned downwards. +      if (RegisterId(Reg) == RegisterId::ESP) { +        Reg = unsigned(RegisterId::VFRAME); +        Offset -= FI.FrameSize; +      } + +      // If we can use the chosen frame pointer for the frame and this isn't a +      // sliced aggregate, use the smaller S_DEFRANGE_FRAMEPOINTER_REL record. +      // Otherwise, use S_DEFRANGE_REGISTER_REL. +      EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU); +      if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None && +          (bool(Flags & LocalSymFlags::IsParameter) +               ? (EncFP == FI.EncodedParamFramePtrReg) +               : (EncFP == FI.EncodedLocalFramePtrReg))) { +        ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_FRAMEPOINTER_REL); +        little32_t FPOffset = little32_t(Offset); +        BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind), +                                sizeof(SymKind)); +        BytePrefix += StringRef(reinterpret_cast<const char *>(&FPOffset), +                                sizeof(FPOffset)); +      } else { +        uint16_t RegRelFlags = 0; +        if (DefRange.IsSubfield) { +          RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag | +                        (DefRange.StructOffset +                         << DefRangeRegisterRelSym::OffsetInParentShift); +        } +        DefRangeRegisterRelSym::Header DRHdr; +        DRHdr.Register = Reg; +        DRHdr.Flags = RegRelFlags; +        DRHdr.BasePointerOffset = Offset; +        ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL); +        BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind), +                                sizeof(SymKind)); +        BytePrefix += StringRef(reinterpret_cast<const char *>(&DRHdr), +                                sizeof(DRHdr));        } -      DefRangeRegisterRelSym Sym(S_DEFRANGE_REGISTER_REL); -      Sym.Hdr.Register = DefRange.CVRegister; -      Sym.Hdr.Flags = RegRelFlags; -      Sym.Hdr.BasePointerOffset = DefRange.DataOffset; -      ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL); -      BytePrefix += -          StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind)); -      BytePrefix += -          StringRef(reinterpret_cast<const char *>(&Sym.Hdr), sizeof(Sym.Hdr));      } else {        assert(DefRange.DataOffset == 0 && "unexpected offset into register");        if (DefRange.IsSubfield) { @@ -2479,7 +2595,7 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,    OS.EmitLabel(RecordEnd);    // Emit variables local to this lexical block. -  emitLocalVariableList(Block.Locals); +  emitLocalVariableList(FI, Block.Locals);    // Emit lexical blocks contained within this block.    emitLexicalBlockList(Block.Children, FI); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 6d7b97c5dd6..3836862f0a8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -54,6 +54,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {    BumpPtrAllocator Allocator;    codeview::GlobalTypeTableBuilder TypeTable; +  /// The codeview CPU type used by the translation unit. +  codeview::CPUType TheCPU; +    /// Represents the most general definition range.    struct LocalVarDefRange {      /// Indicates that variable data is stored in memory relative to the @@ -140,6 +143,28 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {      const MCSymbol *End = nullptr;      unsigned FuncId = 0;      unsigned LastFileId = 0; + +    /// Number of bytes allocated in the prologue for all local stack objects. +    unsigned FrameSize = 0; + +    /// Number of bytes of parameters on the stack. +    unsigned ParamSize = 0; + +    /// Number of bytes pushed to save CSRs. +    unsigned CSRSize = 0; + +    /// Two-bit value indicating which register is the designated frame pointer +    /// register for local variables. Included in S_FRAMEPROC. +    codeview::EncodedFramePtrReg EncodedLocalFramePtrReg = +        codeview::EncodedFramePtrReg::None; + +    /// Two-bit value indicating which register is the designated frame pointer +    /// register for stack parameters. Included in S_FRAMEPROC. +    codeview::EncodedFramePtrReg EncodedParamFramePtrReg = +        codeview::EncodedFramePtrReg::None; + +    codeview::FrameProcedureOptions FrameProcOpts; +      bool HaveLineInfo = false;    };    FunctionInfo *CurFn = nullptr; @@ -293,10 +318,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {    void recordLocalVariable(LocalVariable &&Var, const LexicalScope *LS);    /// Emits local variables in the appropriate order. -  void emitLocalVariableList(ArrayRef<LocalVariable> Locals); +  void emitLocalVariableList(const FunctionInfo &FI, +                             ArrayRef<LocalVariable> Locals);    /// Emits an S_LOCAL record and its associated defined ranges. -  void emitLocalVariable(const LocalVariable &Var); +  void emitLocalVariable(const FunctionInfo &FI, const LocalVariable &Var);    /// Emits a sequence of lexical block scopes and their children.    void emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks, diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp index 3d2db97acb4..0102f1240a8 100644 --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -580,6 +580,7 @@ bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,    MFI.setHasCalls(YamlMFI.HasCalls);    if (YamlMFI.MaxCallFrameSize != ~0u)      MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize); +  MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters);    MFI.setHasOpaqueSPAdjustment(YamlMFI.HasOpaqueSPAdjustment);    MFI.setHasVAStart(YamlMFI.HasVAStart);    MFI.setHasMustTailInVarArgFunc(YamlMFI.HasMustTailInVarArgFunc); diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 20533f90954..88e2f16d3fd 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -328,6 +328,8 @@ void MIRPrinter::convert(ModuleSlotTracker &MST,    YamlMFI.HasCalls = MFI.hasCalls();    YamlMFI.MaxCallFrameSize = MFI.isMaxCallFrameSizeComputed()      ? MFI.getMaxCallFrameSize() : ~0u; +  YamlMFI.CVBytesOfCalleeSavedRegisters = +      MFI.getCVBytesOfCalleeSavedRegisters();    YamlMFI.HasOpaqueSPAdjustment = MFI.hasOpaqueSPAdjustment();    YamlMFI.HasVAStart = MFI.hasVAStart();    YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc(); diff --git a/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index e77c8e8f02f..e73c69fff44 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -471,3 +471,75 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,    return Error::success();  } + +RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg, +                                       CPUType CPU) { +  assert(unsigned(EncodedReg) < 4); +  switch (CPU) { +  // FIXME: Add ARM and AArch64 variants here. +  default: +    break; +  case CPUType::Intel8080: +  case CPUType::Intel8086: +  case CPUType::Intel80286: +  case CPUType::Intel80386: +  case CPUType::Intel80486: +  case CPUType::Pentium: +  case CPUType::PentiumPro: +  case CPUType::Pentium3: +    switch (EncodedReg) { +    case EncodedFramePtrReg::None:     return RegisterId::NONE; +    case EncodedFramePtrReg::StackPtr: return RegisterId::VFRAME; +    case EncodedFramePtrReg::FramePtr: return RegisterId::EBP; +    case EncodedFramePtrReg::BasePtr:  return RegisterId::EBX; +    } +    llvm_unreachable("bad encoding"); +  case CPUType::X64: +    switch (EncodedReg) { +    case EncodedFramePtrReg::None:     return RegisterId::NONE; +    case EncodedFramePtrReg::StackPtr: return RegisterId::RSP; +    case EncodedFramePtrReg::FramePtr: return RegisterId::RBP; +    case EncodedFramePtrReg::BasePtr:  return RegisterId::R13; +    } +    llvm_unreachable("bad encoding"); +  } +  return RegisterId::NONE; +} + +EncodedFramePtrReg codeview::encodeFramePtrReg(RegisterId Reg, CPUType CPU) { +  switch (CPU) { +  // FIXME: Add ARM and AArch64 variants here. +  default: +    break; +  case CPUType::Intel8080: +  case CPUType::Intel8086: +  case CPUType::Intel80286: +  case CPUType::Intel80386: +  case CPUType::Intel80486: +  case CPUType::Pentium: +  case CPUType::PentiumPro: +  case CPUType::Pentium3: +    switch (Reg) { +    case RegisterId::VFRAME: +      return EncodedFramePtrReg::StackPtr; +    case RegisterId::EBP: +      return EncodedFramePtrReg::FramePtr; +    case RegisterId::EBX: +      return EncodedFramePtrReg::BasePtr; +    default: +      break; +    } +  case CPUType::X64: +    switch (Reg) { +    case RegisterId::RSP: +      return EncodedFramePtrReg::StackPtr; +    case RegisterId::RBP: +      return EncodedFramePtrReg::FramePtr; +    case RegisterId::R13: +      return EncodedFramePtrReg::BasePtr; +    default: +      break; +    } +  } +  return EncodedFramePtrReg::None; +} diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 46e30d786f0..2d660ac8826 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1983,6 +1983,7 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots(    }    X86FI->setCalleeSavedFrameSize(CalleeSavedFrameSize); +  MFI.setCVBytesOfCalleeSavedRegisters(CalleeSavedFrameSize);    // Assign slots for XMMs.    for (unsigned i = CSI.size(); i != 0; --i) { diff --git a/llvm/test/CodeGen/MIR/Generic/frame-info.mir b/llvm/test/CodeGen/MIR/Generic/frame-info.mir index 24c0ccde40b..e25bdcfb0d0 100644 --- a/llvm/test/CodeGen/MIR/Generic/frame-info.mir +++ b/llvm/test/CodeGen/MIR/Generic/frame-info.mir @@ -38,6 +38,7 @@ tracksRegLiveness: true  # CHECK-NEXT: hasCalls: false  # CHECK-NEXT: stackProtector:  ''  # CHECK-NEXT: maxCallFrameSize: +# CHECK-NEXT: cvBytesOfCalleeSavedRegisters: 0  # CHECK-NEXT: hasOpaqueSPAdjustment: false  # CHECK-NEXT: hasVAStart: false  # CHECK-NEXT: hasMustTailInVarArgFunc: false @@ -68,6 +69,7 @@ tracksRegLiveness: true  # CHECK-NEXT: hasCalls: true  # CHECK-NEXT: stackProtector:  ''  # CHECK-NEXT: maxCallFrameSize: 4 +# CHECK-NEXT: cvBytesOfCalleeSavedRegisters: 8  # CHECK-NEXT: hasOpaqueSPAdjustment: true  # CHECK-NEXT: hasVAStart: true  # CHECK-NEXT: hasMustTailInVarArgFunc: true @@ -83,6 +85,7 @@ frameInfo:    adjustsStack:    true    hasCalls:        true    maxCallFrameSize: 4 +  cvBytesOfCalleeSavedRegisters: 8    hasOpaqueSPAdjustment: true    hasVAStart:      true    hasMustTailInVarArgFunc: true diff --git a/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir b/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir index f8612bb1b37..3388ef714d4 100644 --- a/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir +++ b/llvm/test/CodeGen/MIR/X86/diexpr-win32.mir @@ -1,5 +1,10 @@  # RUN: llc -start-after=prologepilog -filetype=obj -O0 %s -o - | llvm-readobj -codeview | FileCheck %s -# + +# Offsets are now CFA, or VFRAME, relative. Both the NRVO sret pointer and the +# string* parameter are on the stack, NRVO at offset 4 (after RA), and Str at +# offset 8 (next slot). The stack size is 4, so the DW_OP_plus_uconst math +# works out. +  # (DW_OP_plus_uconst 12)  # CHECK: LocalSym {  # CHECK-NEXT:   Kind: S_LOCAL (0x113E) @@ -8,12 +13,9 @@  # CHECK-NEXT:   ]  # CHECK-NEXT:   VarName: Str  # CHECK-NEXT: } -# CHECK-NEXT: DefRangeRegisterRelSym { -# CHECK-NEXT:   Kind: S_DEFRANGE_REGISTER_REL (0x1145) -# CHECK-NEXT:   BaseRegister: -# CHECK-NEXT:   HasSpilledUDTMember: No -# CHECK-NEXT:   OffsetInParent: 0 -# CHECK-NEXT:   BasePointerOffset: 12 +# CHECK-NEXT: DefRangeFramePointerRelSym { +# CHECK-NEXT:   Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142) +# CHECK-NEXT:   Offset: 8  # CHECK-NEXT:   LocalVariableAddrRange {  # CHECK-NEXT:     OffsetStart:  # CHECK-NEXT:     ISectStart: @@ -28,16 +30,13 @@  # CHECK-NEXT:   ]  # CHECK-NEXT:   VarName: Result  # CHECK-NEXT: } -# CHECK-NEXT: DefRangeRegisterRelSym { -# CHECK-NEXT:   Kind: S_DEFRANGE_REGISTER_REL (0x1145) -# CHECK-NEXT:   BaseRegister: -# CHECK-NEXT:   HasSpilledUDTMember: No -# CHECK-NEXT:   OffsetInParent: 0 -# CHECK-NEXT:   BasePointerOffset: 8 +# CHECK-NEXT: DefRangeFramePointerRelSym { +# CHECK-NEXT:   Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142) +# CHECK-NEXT:   Offset: 4  # CHECK-NEXT:   LocalVariableAddrRange { -# CHECK-NEXT:     OffsetStart: -# CHECK-NEXT:     ISectStart: -# CHECK-NEXT:     Range: +# CHECK-NEXT:     OffsetStart: .text+0x5 +# CHECK-NEXT:     ISectStart: 0x0 +# CHECK-NEXT:     Range: 0x18  # CHECK-NEXT:   }  # CHECK-NEXT: }  # (DW_OP_constu, 4, DW_OP_minus) diff --git a/llvm/test/DebugInfo/COFF/asm.ll b/llvm/test/DebugInfo/COFF/asm.ll index fa2a25894f6..ed71b246f3c 100644 --- a/llvm/test/DebugInfo/COFF/asm.ll +++ b/llvm/test/DebugInfo/COFF/asm.ll @@ -99,7 +99,7 @@  ; OBJ64:          DisplayName: f  ; OBJ64:          LinkageName: f  ; OBJ64:        } -; OBJ64-NEXT:   ProcEnd { +; OBJ64:        ProcEnd {  ; OBJ64:        }  ; OBJ64-NEXT: ]  ; OBJ64:      FunctionLineTable [ diff --git a/llvm/test/DebugInfo/COFF/frameproc-flags.ll b/llvm/test/DebugInfo/COFF/frameproc-flags.ll new file mode 100644 index 00000000000..a9d0fe067da --- /dev/null +++ b/llvm/test/DebugInfo/COFF/frameproc-flags.ll @@ -0,0 +1,379 @@ +; RUN: llc -filetype=obj %s -o %t.obj +; RUN: llvm-pdbutil dump %t.obj -symbols | FileCheck %s + +; A fairly exhaustive test of S_FRAMEPROC flags. Use the source below to compare +; the flags we set with MSVC. + +; extern "C" { +; +; void *_alloca(size_t); +; struct __declspec(align(16)) _jmp_buf_str { +;   unsigned __int64 Part[2]; +; }; +; typedef struct _jmp_buf_str jmp_buf[16]; +; int __cdecl _setjmp(jmp_buf _Buf); +; +; void may_throw(void); +; void use_intptr(int *); +; +; void use_alloca(int n) { +;   int *p = (int*)_alloca(n * sizeof(int)); +;   use_intptr(p); +; } +; +; jmp_buf g_jbuf; +; void call_setjmp(int n) { +;   if (!_setjmp(g_jbuf)) +;     use_intptr(nullptr); +; } +; +; void use_inlineasm() { +;   __asm nop +; } +; +; void cpp_eh() { +;   try { +;     may_throw(); +;   } catch (...) { +;   } +; } +; +; static inline int is_marked_inline(int x, int y) { +;   return x + y; +; } +; int (*use_inline())(int x, int y) { +;   return &is_marked_inline; +; } +; +; void seh() { +;   __try { +;     may_throw(); +;   } __except (1) { +;   } +; } +; +; void __declspec(naked) use_naked() { +;   __asm ret +; } +; +; void stack_guard() { +;   int arr[12] = {0}; +;   use_intptr(&arr[0]); +; } +; } + +; CHECK-LABEL: S_GPROC32_ID [size = 50] `use_alloca` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = VFRAME, param fp reg = EBP +; CHECK:   flags = has alloca | secure checks | opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 51] `call_setjmp` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = NONE, param fp reg = NONE +; CHECK:   flags = has setjmp | opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 53] `use_inlineasm` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = NONE, param fp reg = NONE +; CHECK:   flags = has inline asm | opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 46] `cpp_eh` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = EBP, param fp reg = EBP +; CHECK:   flags = has eh | opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 50] `use_inline` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = NONE, param fp reg = NONE +; CHECK:   flags = opt speed +; CHECK-LABEL: S_LPROC32_ID [size = 56] `is_marked_inline` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = NONE, param fp reg = NONE +; CHECK:   flags = marked inline | opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 43] `seh` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = EBP, param fp reg = EBP +; CHECK:   flags = has seh | opt speed +; CHECK-LABEL: S_LPROC32_ID [size = 55] `?filt$0@0@seh@@` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = EBP, param fp reg = EBP +; CHECK:   flags = opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 49] `use_naked` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = NONE, param fp reg = NONE +; CHECK:   flags = has inline asm | naked | opt speed +; CHECK-LABEL: S_GPROC32_ID [size = 51] `stack_guard` +; CHECK: S_FRAMEPROC [size = 30] +; CHECK:   local fp reg = VFRAME, param fp reg = EBP +; CHECK:   flags = secure checks | opt speed + +; ModuleID = 'frameproc-flags.cpp' +source_filename = "frameproc-flags.cpp" +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc19.14.26433" + +%struct._jmp_buf_str = type { [2 x i64] } + +@g_jbuf = dso_local global [16 x %struct._jmp_buf_str] zeroinitializer, align 16, !dbg !0 + +define dso_local void @use_alloca(i32 %n) local_unnamed_addr #0 !dbg !25 { +entry: +  call void @llvm.dbg.value(metadata i32 %n, metadata !29, metadata !DIExpression()), !dbg !31 +  %mul = shl i32 %n, 2, !dbg !32 +  %0 = alloca i8, i32 %mul, align 16, !dbg !32 +  %1 = bitcast i8* %0 to i32*, !dbg !32 +  call void @llvm.dbg.value(metadata i32* %1, metadata !30, metadata !DIExpression()), !dbg !32 +  call void @use_intptr(i32* nonnull %1), !dbg !33 +  ret void, !dbg !34 +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #2 + +declare dso_local void @use_intptr(i32*) local_unnamed_addr #3 + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #2 + +define dso_local void @call_setjmp(i32 %n) local_unnamed_addr #0 !dbg !35 { +entry: +  call void @llvm.dbg.value(metadata i32 %n, metadata !37, metadata !DIExpression()), !dbg !38 +  %0 = call i32 (i8*, i32, ...) @_setjmp3(i8* bitcast ([16 x %struct._jmp_buf_str]* @g_jbuf to i8*), i32 0) #4, !dbg !39 +  %tobool = icmp eq i32 %0, 0, !dbg !39 +  br i1 %tobool, label %if.then, label %if.end, !dbg !39 + +if.then:                                          ; preds = %entry +  call void @use_intptr(i32* null), !dbg !40 +  br label %if.end, !dbg !40 + +if.end:                                           ; preds = %entry, %if.then +  ret void, !dbg !42 +} + +; Function Attrs: returns_twice +declare dso_local i32 @_setjmp3(i8*, i32, ...) local_unnamed_addr #4 + +; Function Attrs: nounwind +define dso_local void @use_inlineasm() local_unnamed_addr #5 !dbg !43 { +entry: +  tail call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() #10, !dbg !46, !srcloc !47 +  ret void, !dbg !48 +} + +define dso_local void @cpp_eh() local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) !dbg !49 { +entry: +  invoke void @may_throw() +          to label %try.cont unwind label %catch.dispatch, !dbg !50 + +catch.dispatch:                                   ; preds = %entry +  %0 = catchswitch within none [label %catch] unwind to caller, !dbg !52 + +catch:                                            ; preds = %catch.dispatch +  %1 = catchpad within %0 [i8* null, i32 64, i8* null], !dbg !52 +  catchret from %1 to label %try.cont, !dbg !53 + +try.cont:                                         ; preds = %entry, %catch +  ret void, !dbg !55 +} + +declare dso_local void @may_throw() local_unnamed_addr #3 + +declare dso_local i32 @__CxxFrameHandler3(...) + +; Function Attrs: norecurse nounwind readnone +define dso_local nonnull i32 (i32, i32)* @use_inline() local_unnamed_addr #6 !dbg !56 { +entry: +  ret i32 (i32, i32)* @"?is_marked_inline@@YAHHH@Z", !dbg !62 +} + +; Function Attrs: inlinehint nounwind readnone +define internal i32 @"?is_marked_inline@@YAHHH@Z"(i32 %x, i32 %y) #7 !dbg !63 { +entry: +  call void @llvm.dbg.value(metadata i32 %y, metadata !65, metadata !DIExpression()), !dbg !67 +  call void @llvm.dbg.value(metadata i32 %x, metadata !66, metadata !DIExpression()), !dbg !67 +  %add = add nsw i32 %y, %x, !dbg !68 +  ret i32 %add, !dbg !68 +} + +define dso_local void @seh() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) !dbg !69 { +entry: +  %__exception_code = alloca i32, align 4 +  call void (...) @llvm.localescape(i32* nonnull %__exception_code) +  invoke void @may_throw() #12 +          to label %__try.cont unwind label %catch.dispatch, !dbg !70 + +catch.dispatch:                                   ; preds = %entry +  %0 = catchswitch within none [label %__except.ret] unwind to caller, !dbg !72 + +__except.ret:                                     ; preds = %catch.dispatch +  %1 = catchpad within %0 [i8* bitcast (i32 ()* @"?filt$0@0@seh@@" to i8*)], !dbg !72 +  catchret from %1 to label %__try.cont, !dbg !72 + +__try.cont:                                       ; preds = %entry, %__except.ret +  ret void, !dbg !73 +} + +; Function Attrs: nounwind +define internal i32 @"?filt$0@0@seh@@"() #8 !dbg !74 { +entry: +  %0 = tail call i8* @llvm.frameaddress(i32 1) +  %1 = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @seh to i8*), i8* %0) +  %2 = tail call i8* @llvm.localrecover(i8* bitcast (void ()* @seh to i8*), i8* %1, i32 0) +  %__exception_code = bitcast i8* %2 to i32* +  %3 = getelementptr inbounds i8, i8* %0, i32 -20, !dbg !76 +  %4 = bitcast i8* %3 to { i32*, i8* }**, !dbg !76 +  %5 = load { i32*, i8* }*, { i32*, i8* }** %4, align 4, !dbg !76 +  %6 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %5, i32 0, i32 0, !dbg !76 +  %7 = load i32*, i32** %6, align 4, !dbg !76 +  %8 = load i32, i32* %7, align 4, !dbg !76 +  store i32 %8, i32* %__exception_code, align 4, !dbg !76 +  ret i32 1, !dbg !76 +} + +; Function Attrs: nounwind readnone +declare i8* @llvm.frameaddress(i32) #9 + +; Function Attrs: nounwind readnone +declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #9 + +; Function Attrs: nounwind readnone +declare i8* @llvm.localrecover(i8*, i8*, i32) #9 + +declare dso_local i32 @_except_handler3(...) + +; Function Attrs: nounwind +declare void @llvm.localescape(...) #10 + +; Function Attrs: naked noinline nounwind +define dso_local void @use_naked() #11 !dbg !77 { +entry: +  tail call void asm sideeffect inteldialect "ret", "~{dirflag},~{fpsr},~{flags}"() #10, !dbg !78, !srcloc !79 +  unreachable, !dbg !80 +} + +define dso_local void @stack_guard() local_unnamed_addr #0 !dbg !81 { +entry: +  %arr = alloca [12 x i32], align 4 +  %0 = bitcast [12 x i32]* %arr to i8*, !dbg !87 +  call void @llvm.lifetime.start.p0i8(i64 48, i8* nonnull %0) #10, !dbg !87 +  call void @llvm.dbg.declare(metadata [12 x i32]* %arr, metadata !83, metadata !DIExpression()), !dbg !87 +  call void @llvm.memset.p0i8.i32(i8* nonnull align 4 %0, i8 0, i32 48, i1 false), !dbg !87 +  %arrayidx = getelementptr inbounds [12 x i32], [12 x i32]* %arr, i32 0, i32 0, !dbg !88 +  call void @use_intptr(i32* nonnull %arrayidx), !dbg !88 +  call void @llvm.lifetime.end.p0i8(i64 48, i8* nonnull %0) #10, !dbg !89 +  ret void, !dbg !89 +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable } +attributes #2 = { argmemonly nounwind } +attributes #3 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { returns_twice } +attributes #5 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #6 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #7 = { inlinehint nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #8 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #9 = { nounwind readnone } +attributes #10 = { nounwind } +attributes #11 = { naked noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #12 = { noinline } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!20, !21, !22, !23} +!llvm.ident = !{!24} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g_jbuf", scope: !2, file: !3, line: 18, type: !9, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 8.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !8, nameTableKind: None) +!3 = !DIFile(filename: "frameproc-flags.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "1dd66a71668512c95552767c3a35300a") +!4 = !{} +!5 = !{!6} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{!0} +!9 = !DIDerivedType(tag: DW_TAG_typedef, name: "jmp_buf", file: !3, line: 7, baseType: !10) +!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 2048, elements: !18) +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_jmp_buf_str", file: !3, line: 4, size: 128, align: 128, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !12, identifier: ".?AU_jmp_buf_str@@") +!12 = !{!13} +!13 = !DIDerivedType(tag: DW_TAG_member, name: "Part", scope: !11, file: !3, line: 5, baseType: !14, size: 128) +!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 128, elements: !16) +!15 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!16 = !{!17} +!17 = !DISubrange(count: 2) +!18 = !{!19} +!19 = !DISubrange(count: 16) +!20 = !{i32 1, !"NumRegisterParameters", i32 0} +!21 = !{i32 2, !"CodeView", i32 1} +!22 = !{i32 2, !"Debug Info Version", i32 3} +!23 = !{i32 1, !"wchar_size", i32 2} +!24 = !{!"clang version 8.0.0 "} +!25 = distinct !DISubprogram(name: "use_alloca", scope: !3, file: !3, line: 13, type: !26, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !28) +!26 = !DISubroutineType(types: !27) +!27 = !{null, !7} +!28 = !{!29, !30} +!29 = !DILocalVariable(name: "n", arg: 1, scope: !25, file: !3, line: 13, type: !7) +!30 = !DILocalVariable(name: "p", scope: !25, file: !3, line: 14, type: !6) +!31 = !DILocation(line: 13, scope: !25) +!32 = !DILocation(line: 14, scope: !25) +!33 = !DILocation(line: 15, scope: !25) +!34 = !DILocation(line: 16, scope: !25) +!35 = distinct !DISubprogram(name: "call_setjmp", scope: !3, file: !3, line: 19, type: !26, isLocal: false, isDefinition: true, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !36) +!36 = !{!37} +!37 = !DILocalVariable(name: "n", arg: 1, scope: !35, file: !3, line: 19, type: !7) +!38 = !DILocation(line: 19, scope: !35) +!39 = !DILocation(line: 20, scope: !35) +!40 = !DILocation(line: 21, scope: !41) +!41 = distinct !DILexicalBlock(scope: !35, file: !3, line: 20) +!42 = !DILocation(line: 22, scope: !35) +!43 = distinct !DISubprogram(name: "use_inlineasm", scope: !3, file: !3, line: 24, type: !44, isLocal: false, isDefinition: true, scopeLine: 24, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4) +!44 = !DISubroutineType(types: !45) +!45 = !{null} +!46 = !DILocation(line: 25, scope: !43) +!47 = !{i32 445} +!48 = !DILocation(line: 26, scope: !43) +!49 = distinct !DISubprogram(name: "cpp_eh", scope: !3, file: !3, line: 28, type: !44, isLocal: false, isDefinition: true, scopeLine: 28, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4) +!50 = !DILocation(line: 30, scope: !51) +!51 = distinct !DILexicalBlock(scope: !49, file: !3, line: 29) +!52 = !DILocation(line: 31, scope: !51) +!53 = !DILocation(line: 32, scope: !54) +!54 = distinct !DILexicalBlock(scope: !49, file: !3, line: 31) +!55 = !DILocation(line: 33, scope: !49) +!56 = distinct !DISubprogram(name: "use_inline", scope: !3, file: !3, line: 38, type: !57, isLocal: false, isDefinition: true, scopeLine: 38, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4) +!57 = !DISubroutineType(types: !58) +!58 = !{!59} +!59 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !60, size: 32) +!60 = !DISubroutineType(types: !61) +!61 = !{!7, !7, !7} +!62 = !DILocation(line: 39, scope: !56) +!63 = distinct !DISubprogram(name: "is_marked_inline", linkageName: "?is_marked_inline@@YAHHH@Z", scope: !3, file: !3, line: 35, type: !60, isLocal: true, isDefinition: true, scopeLine: 35, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !64) +!64 = !{!65, !66} +!65 = !DILocalVariable(name: "y", arg: 2, scope: !63, file: !3, line: 35, type: !7) +!66 = !DILocalVariable(name: "x", arg: 1, scope: !63, file: !3, line: 35, type: !7) +!67 = !DILocation(line: 35, scope: !63) +!68 = !DILocation(line: 36, scope: !63) +!69 = distinct !DISubprogram(name: "seh", scope: !3, file: !3, line: 42, type: !44, isLocal: false, isDefinition: true, scopeLine: 42, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4) +!70 = !DILocation(line: 44, scope: !71) +!71 = distinct !DILexicalBlock(scope: !69, file: !3, line: 43) +!72 = !DILocation(line: 45, scope: !71) +!73 = !DILocation(line: 47, scope: !69) +!74 = distinct !DISubprogram(linkageName: "?filt$0@0@seh@@", scope: !3, file: !3, line: 45, type: !75, isLocal: true, isDefinition: true, scopeLine: 45, flags: DIFlagArtificial, isOptimized: true, unit: !2, retainedNodes: !4) +!75 = !DISubroutineType(types: !4) +!76 = !DILocation(line: 45, scope: !74) +!77 = distinct !DISubprogram(name: "use_naked", scope: !3, file: !3, line: 49, type: !44, isLocal: false, isDefinition: true, scopeLine: 49, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4) +!78 = !DILocation(line: 50, scope: !77) +!79 = !{i32 765} +!80 = !DILocation(line: 51, scope: !77) +!81 = distinct !DISubprogram(name: "stack_guard", scope: !3, file: !3, line: 53, type: !44, isLocal: false, isDefinition: true, scopeLine: 53, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !82) +!82 = !{!83} +!83 = !DILocalVariable(name: "arr", scope: !81, file: !3, line: 54, type: !84) +!84 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 384, elements: !85) +!85 = !{!86} +!86 = !DISubrange(count: 12) +!87 = !DILocation(line: 54, scope: !81) +!88 = !DILocation(line: 55, scope: !81) +!89 = !DILocation(line: 56, scope: !81) diff --git a/llvm/test/DebugInfo/COFF/local-variables.ll b/llvm/test/DebugInfo/COFF/local-variables.ll index 683b438d396..085ced17262 100644 --- a/llvm/test/DebugInfo/COFF/local-variables.ll +++ b/llvm/test/DebugInfo/COFF/local-variables.ll @@ -71,30 +71,30 @@  ; ASM: .long   116                     # TypeIndex  ; ASM: .short  1                       # Flags  ; ASM: .asciz  "param" -; ASM: .cv_def_range    [[prologue_end]] [[param_end]], "E\021O\001\000\0004\000\000\000" +; ASM: .cv_def_range    [[prologue_end]] [[param_end]], "B\0214\000\000\000"  ; ASM: .short  4414                    # Record kind: S_LOCAL  ; ASM: .long   116                     # TypeIndex  ; ASM: .short  0                       # Flags  ; ASM: .asciz  "a" -; ASM: .cv_def_range    [[if_start]] [[else_start]], "E\021O\001\000\000(\000\000\000" +; ASM: .cv_def_range    [[if_start]] [[else_start]], "B\021(\000\000\000"  ; ASM: .short  4414                    # Record kind: S_LOCAL  ; ASM: .long   116                     # TypeIndex  ; ASM: .short  0                       # Flags  ; ASM: .asciz  "b" -; ASM: .cv_def_range    [[else_start]] [[else_end]], "E\021O\001\000\000$\000\000\000" +; ASM: .cv_def_range    [[else_start]] [[else_end]], "B\021$\000\000\000"  ; ASM: .short  4429                    # Record kind: S_INLINESITE  ; ASM: .short  4414                    # Record kind: S_LOCAL  ; ASM: .long   116                     # TypeIndex  ; ASM: .short  0                       # Flags  ; ASM: .asciz  "v" -; ASM: .cv_def_range    [[inline_site1]] [[else_start]], "E\021O\001\000\000,\000\000\000" +; ASM: .cv_def_range    [[inline_site1]] [[else_start]], "B\021,\000\000\000"  ; ASM: .short  4430                    # Record kind: S_INLINESITE_END  ; ASM: .short  4429                    # Record kind: S_INLINESITE  ; ASM: .short  4414                    # Record kind: S_LOCAL  ; ASM: .long   116                     # TypeIndex  ; ASM: .short  0                       # Flags  ; ASM: .asciz  "v" -; ASM: .cv_def_range    [[inline_site2]] [[else_end]], "E\021O\001\000\0000\000\000\000" +; ASM: .cv_def_range    [[inline_site2]] [[else_end]], "B\0210\000\000\000"  ; ASM: .short  4430                    # Record kind: S_INLINESITE_END  ; OBJ:  Subsection [ @@ -110,11 +110,8 @@  ; OBJ:      ]  ; OBJ:      VarName: param  ; OBJ:    } -; OBJ:    DefRangeRegisterRelSym { -; OBJ:      BaseRegister: RSP (0x14F) -; OBJ:      HasSpilledUDTMember: No -; OBJ:      OffsetInParent: 0 -; OBJ:      BasePointerOffset: 52 +; OBJ:    DefRangeFramePointerRelSym { +; OBJ:      Offset: 52  ; OBJ:      LocalVariableAddrRange {  ; OBJ:        OffsetStart: .text+0x8  ; OBJ:        ISectStart: 0x0 @@ -127,11 +124,8 @@  ; OBJ:      ]  ; OBJ:      VarName: a  ; OBJ:    } -; OBJ:    DefRangeRegisterRelSym { -; OBJ:      BaseRegister: RSP (0x14F) -; OBJ:      HasSpilledUDTMember: No -; OBJ:      OffsetInParent: 0 -; OBJ:      BasePointerOffset: 40 +; OBJ:    DefRangeFramePointerRelSym { +; OBJ:      Offset: 40  ; OBJ:      LocalVariableAddrRange {  ; OBJ:        OffsetStart: .text+0xC  ; OBJ:        ISectStart: 0x0 @@ -144,11 +138,8 @@  ; OBJ:      ]  ; OBJ:      VarName: b  ; OBJ:    } -; OBJ:    DefRangeRegisterRelSym { -; OBJ:      BaseRegister: RSP (0x14F) -; OBJ:      HasSpilledUDTMember: No -; OBJ:      OffsetInParent: 0 -; OBJ:      BasePointerOffset: 36 +; OBJ:    DefRangeFramePointerRelSym { +; OBJ:      Offset: 36  ; OBJ:      LocalVariableAddrRange {  ; OBJ:        OffsetStart: .text+0x2D  ; OBJ:        ISectStart: 0x0 @@ -172,11 +163,8 @@  ; OBJ:      ]  ; OBJ:      VarName: v  ; OBJ:    } -; OBJ:    DefRangeRegisterRelSym { -; OBJ:      BaseRegister: RSP (0x14F) -; OBJ:      HasSpilledUDTMember: No -; OBJ:      OffsetInParent: 0 -; OBJ:      BasePointerOffset: 44 +; OBJ:    DefRangeFramePointerRelSym { +; OBJ:      Offset: 44  ; OBJ:      LocalVariableAddrRange {  ; OBJ:        OffsetStart: .text+0x14  ; OBJ:        ISectStart: 0x0 @@ -202,11 +190,8 @@  ; OBJ:      ]  ; OBJ:      VarName: v  ; OBJ:    } -; OBJ:    DefRangeRegisterRelSym { -; OBJ:      BaseRegister: RSP (0x14F) -; OBJ:      HasSpilledUDTMember: No -; OBJ:      OffsetInParent: 0 -; OBJ:      BasePointerOffset: 48 +; OBJ:    DefRangeFramePointerRelSym { +; OBJ:      Offset: 48  ; OBJ:      LocalVariableAddrRange {  ; OBJ:        OffsetStart: .text+0x35  ; OBJ:        ISectStart: 0x0 diff --git a/llvm/test/DebugInfo/COFF/multifile.ll b/llvm/test/DebugInfo/COFF/multifile.ll index ea6e758a243..cb281ea7a4d 100644 --- a/llvm/test/DebugInfo/COFF/multifile.ll +++ b/llvm/test/DebugInfo/COFF/multifile.ll @@ -48,7 +48,7 @@  ; OBJ32:          DisplayName: f  ; OBJ32:          LinkageName: _f  ; OBJ32:        } -; OBJ32-NEXT:   ProcEnd { +; OBJ32:        ProcEnd {  ; OBJ32:        }  ; OBJ32-NEXT: ]  ; OBJ32:	  Subsection [ @@ -136,7 +136,7 @@  ; OBJ64:          DisplayName: f  ; OBJ64:          LinkageName: f  ; OBJ64:        } -; OBJ64-NEXT:   ProcEnd { +; OBJ64:        ProcEnd {  ; OBJ64:        }  ; OBJ64-NEXT: ]  ; OBJ64:	  Subsection [ diff --git a/llvm/test/DebugInfo/COFF/multifunction.ll b/llvm/test/DebugInfo/COFF/multifunction.ll index c675edab5aa..c74b332d8b8 100644 --- a/llvm/test/DebugInfo/COFF/multifunction.ll +++ b/llvm/test/DebugInfo/COFF/multifunction.ll @@ -81,6 +81,17 @@  ; X86-NEXT: .byte   0  ; X86-NEXT: .asciz "x"  ; X86-NEXT: [[PROC_SEGMENT_END]]: +; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X86-NEXT: [[FPROC_BEG]]: +; X86-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X86-NEXT: .long   0                       # FrameSize +; X86-NEXT: .long   0                       # Padding +; X86-NEXT: .long   0                       # Offset of padding +; X86-NEXT: .long   0                       # Bytes of callee saved registers +; X86-NEXT: .long   0                       # Exception handler offset +; X86-NEXT: .short  0                       # Exception handler section +; X86-NEXT: .long   0                       # Flags (defines frame register) +; X86-NEXT: [[FPROC_END]]:  ; X86-NEXT: .short  2  ; X86-NEXT: .short  4431  ; X86-NEXT: [[F1_END]]: @@ -107,6 +118,17 @@  ; X86-NEXT: .byte   0  ; X86-NEXT: .asciz "y"  ; X86-NEXT: [[PROC_SEGMENT_END]]: +; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X86-NEXT: [[FPROC_BEG]]: +; X86-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X86-NEXT: .long   0                       # FrameSize +; X86-NEXT: .long   0                       # Padding +; X86-NEXT: .long   0                       # Offset of padding +; X86-NEXT: .long   0                       # Bytes of callee saved registers +; X86-NEXT: .long   0                       # Exception handler offset +; X86-NEXT: .short  0                       # Exception handler section +; X86-NEXT: .long   0                       # Flags (defines frame register) +; X86-NEXT: [[FPROC_END]]:  ; X86-NEXT: .short  2  ; X86-NEXT: .short  4431  ; X86-NEXT: [[COMPILE_END]]: @@ -133,6 +155,17 @@  ; X86-NEXT: .byte   0  ; X86-NEXT: .asciz "f"  ; X86-NEXT: [[PROC_SEGMENT_END]]: +; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X86-NEXT: [[FPROC_BEG]]: +; X86-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X86-NEXT: .long   0                       # FrameSize +; X86-NEXT: .long   0                       # Padding +; X86-NEXT: .long   0                       # Offset of padding +; X86-NEXT: .long   0                       # Bytes of callee saved registers +; X86-NEXT: .long   0                       # Exception handler offset +; X86-NEXT: .short  0                       # Exception handler section +; X86-NEXT: .long   0                       # Flags (defines frame register) +; X86-NEXT: [[FPROC_END]]:  ; X86-NEXT: .short  2  ; X86-NEXT: .short  4431  ; X86-NEXT: [[COMPILE_END]]: @@ -354,6 +387,17 @@  ; X64-NEXT: .byte   0  ; X64-NEXT: .asciz "x"  ; X64-NEXT: [[PROC_SEGMENT_END]]: +; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X64-NEXT: [[FPROC_BEG]]: +; X64-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X64-NEXT: .long   40                       # FrameSize +; X64-NEXT: .long   0                       # Padding +; X64-NEXT: .long   0                       # Offset of padding +; X64-NEXT: .long   0                       # Bytes of callee saved registers +; X64-NEXT: .long   0                       # Exception handler offset +; X64-NEXT: .short  0                       # Exception handler section +; X64-NEXT: .long   81920                       # Flags (defines frame register) +; X64-NEXT: [[FPROC_END]]:  ; X64-NEXT: .short  2  ; X64-NEXT: .short  4431  ; X64-NEXT: [[F1_END]]: @@ -379,6 +423,17 @@  ; X64-NEXT: .byte   0  ; X64-NEXT: .asciz "y"  ; X64-NEXT: [[PROC_SEGMENT_END]]: +; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X64-NEXT: [[FPROC_BEG]]: +; X64-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X64-NEXT: .long   40                       # FrameSize +; X64-NEXT: .long   0                       # Padding +; X64-NEXT: .long   0                       # Offset of padding +; X64-NEXT: .long   0                       # Bytes of callee saved registers +; X64-NEXT: .long   0                       # Exception handler offset +; X64-NEXT: .short  0                       # Exception handler section +; X64-NEXT: .long   81920                       # Flags (defines frame register) +; X64-NEXT: [[FPROC_END]]:  ; X64-NEXT: .short  2  ; X64-NEXT: .short  4431  ; X64-NEXT: [[COMPILE_END]]: @@ -404,6 +459,17 @@  ; X64-NEXT: .byte   0  ; X64-NEXT: .asciz "f"  ; X64-NEXT: [[PROC_SEGMENT_END]]: +; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X64-NEXT: [[FPROC_BEG]]: +; X64-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X64-NEXT: .long   40                       # FrameSize +; X64-NEXT: .long   0                       # Padding +; X64-NEXT: .long   0                       # Offset of padding +; X64-NEXT: .long   0                       # Bytes of callee saved registers +; X64-NEXT: .long   0                       # Exception handler offset +; X64-NEXT: .short  0                       # Exception handler section +; X64-NEXT: .long   81920                       # Flags (defines frame register) +; X64-NEXT: [[FPROC_END]]:  ; X64-NEXT: .short  2  ; X64-NEXT: .short  4431  ; X64-NEXT: [[COMPILE_END]]: @@ -422,16 +488,16 @@  ; OBJ64:      Relocations [  ; OBJ64-NEXT:   0x64 IMAGE_REL_AMD64_SECREL x  ; OBJ64-NEXT:   0x68 IMAGE_REL_AMD64_SECTION x -; OBJ64-NEXT:   0x7C IMAGE_REL_AMD64_SECREL x -; OBJ64-NEXT:   0x80 IMAGE_REL_AMD64_SECTION x -; OBJ64-NEXT:   0xE0 IMAGE_REL_AMD64_SECREL y -; OBJ64-NEXT:   0xE4 IMAGE_REL_AMD64_SECTION y -; OBJ64-NEXT:   0xF8 IMAGE_REL_AMD64_SECREL y -; OBJ64-NEXT:   0xFC IMAGE_REL_AMD64_SECTION y -; OBJ64-NEXT:   0x15C IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT:   0x160 IMAGE_REL_AMD64_SECTION f -; OBJ64-NEXT:   0x174 IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT:   0x178 IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT:   0x98 IMAGE_REL_AMD64_SECREL x +; OBJ64-NEXT:   0x9C IMAGE_REL_AMD64_SECTION x +; OBJ64-NEXT:   0xFC IMAGE_REL_AMD64_SECREL y +; OBJ64-NEXT:   0x100 IMAGE_REL_AMD64_SECTION y +; OBJ64-NEXT:   0x130 IMAGE_REL_AMD64_SECREL y +; OBJ64-NEXT:   0x134 IMAGE_REL_AMD64_SECTION y +; OBJ64-NEXT:   0x194 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT:   0x198 IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT:   0x1C8 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT:   0x1CC IMAGE_REL_AMD64_SECTION f  ; OBJ64-NEXT: ]  ; OBJ64:      Subsection [  ; OBJ64-NEXT:   SubSectionType: Symbols (0xF1) diff --git a/llvm/test/DebugInfo/COFF/pieces.ll b/llvm/test/DebugInfo/COFF/pieces.ll index ab3794dd0b7..10a81e17d92 100644 --- a/llvm/test/DebugInfo/COFF/pieces.ll +++ b/llvm/test/DebugInfo/COFF/pieces.ll @@ -108,7 +108,7 @@  ; ASM:        .cv_def_range    [[oy_start]] [[oy_end]], "C\021\027\000\000\000\004\000\000\000" -; OBJ-LABEL: {{.*}}Proc{{.*}}Sym { +; OBJ-LABEL: GlobalProcIdSym {  ; OBJ:         Kind: S_GPROC32_ID (0x1147)  ; OBJ:         DisplayName: loop_csr  ; OBJ:       } @@ -138,7 +138,7 @@  ; ASM:        .asciz  "o"  ; ASM:        .cv_def_range    .Lfunc_begin1 .Ltmp8, "C\021\021\000\000\000\004\000\000\000" -; OBJ-LABEL: {{.*}}Proc{{.*}}Sym { +; OBJ-LABEL: GlobalProcIdSym {  ; OBJ:         Kind: S_GPROC32_ID (0x1147)  ; OBJ:         DisplayName: pad_right  ; OBJ:       } @@ -161,7 +161,7 @@  ; ASM:        .asciz  "o"  ; ASM:        .cv_def_range    .Lfunc_begin2 .Ltmp10, "C\021\021\000\000\000\000\000\000\000" -; OBJ-LABEL: {{.*}}Proc{{.*}}Sym { +; OBJ-LABEL: GlobalProcIdSym {  ; OBJ:         Kind: S_GPROC32_ID (0x1147)  ; OBJ:         DisplayName: pad_left  ; OBJ:       } @@ -187,7 +187,7 @@  ; ASM:        .asciz  "p"  ; ASM:        .cv_def_range    [[p_start]] .Lfunc_end3, "C\021\021\000\000\000\004\000\000\000" -; OBJ-LABEL: {{.*}}Proc{{.*}}Sym { +; OBJ-LABEL: GlobalProcIdSym {  ; OBJ:         Kind: S_GPROC32_ID (0x1147)  ; OBJ:         DisplayName: nested  ; OBJ:       } @@ -223,7 +223,7 @@  ; ASM:        .asciz  "o"  ; ASM:        .cv_def_range    [[spill_o_x_start]] [[spill_o_x_end]], "E\021O\001A\000$\000\000\000" -; OBJ-LABEL: {{.*}}Proc{{.*}}Sym { +; OBJ-LABEL: GlobalProcIdSym {  ; OBJ:         Kind: S_GPROC32_ID (0x1147)  ; OBJ:         DisplayName: bitpiece_spill  ; OBJ:       } diff --git a/llvm/test/DebugInfo/COFF/simple.ll b/llvm/test/DebugInfo/COFF/simple.ll index 175be1ab424..3c495a33b8a 100644 --- a/llvm/test/DebugInfo/COFF/simple.ll +++ b/llvm/test/DebugInfo/COFF/simple.ll @@ -59,6 +59,17 @@  ; X86-NEXT: .byte   0  ; X86-NEXT: .asciz "f"  ; X86-NEXT: [[PROC_SEGMENT_END]]: +; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X86-NEXT: [[FPROC_BEG]]: +; X86-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X86-NEXT: .long   0                       # FrameSize +; X86-NEXT: .long   0                       # Padding +; X86-NEXT: .long   0                       # Offset of padding +; X86-NEXT: .long   0                       # Bytes of callee saved registers +; X86-NEXT: .long   0                       # Exception handler offset +; X86-NEXT: .short  0                       # Exception handler section +; X86-NEXT: .long   0                       # Flags (defines frame register) +; X86-NEXT: [[FPROC_END]]:  ; X86-NEXT: .short  2  ; X86-NEXT: .short  4431  ; X86-NEXT: [[F1_END]]: @@ -78,8 +89,8 @@  ; OBJ32-NEXT:   0x44 IMAGE_REL_I386_DIR32NB _f  ; OBJ32-NEXT:   0x90 IMAGE_REL_I386_SECREL _f  ; OBJ32-NEXT:   0x94 IMAGE_REL_I386_SECTION _f -; OBJ32-NEXT:   0xA8 IMAGE_REL_I386_SECREL _f -; OBJ32-NEXT:   0xAC IMAGE_REL_I386_SECTION _f +; OBJ32-NEXT:   0xC4 IMAGE_REL_I386_SECREL _f +; OBJ32-NEXT:   0xC8 IMAGE_REL_I386_SECTION _f  ; OBJ32-NEXT: ]  ; OBJ32:      Subsection [  ; OBJ32-NEXT:   SubSectionType: Symbols (0xF1) @@ -95,7 +106,7 @@  ; OBJ32:          DisplayName: f  ; OBJ32:          LinkageName: _f  ; OBJ32:        } -; OBJ32-NEXT:   ProcEnd { +; OBJ32:        ProcEnd {  ; OBJ32:        }  ; OBJ32-NEXT: ]  ; OBJ32:       Subsection [ @@ -174,6 +185,17 @@  ; X64-NEXT: .byte   0  ; X64-NEXT: .asciz "f"  ; X64-NEXT: [[PROC_SEGMENT_END]]: +; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length +; X64-NEXT: [[FPROC_BEG]]: +; X64-NEXT: .short  4114                    # Record kind: S_FRAMEPROC +; X64-NEXT: .long   40                       # FrameSize +; X64-NEXT: .long   0                       # Padding +; X64-NEXT: .long   0                       # Offset of padding +; X64-NEXT: .long   0                       # Bytes of callee saved registers +; X64-NEXT: .long   0                       # Exception handler offset +; X64-NEXT: .short  0                       # Exception handler section +; X64-NEXT: .long   81920                       # Flags (defines frame register) +; X64-NEXT: [[FPROC_END]]:  ; X64-NEXT: .short  2  ; X64-NEXT: .short  4431  ; X64-NEXT: [[F1_END]]: @@ -192,8 +214,8 @@  ; OBJ64:      Relocations [  ; OBJ64-NEXT:   0x64 IMAGE_REL_AMD64_SECREL f  ; OBJ64-NEXT:   0x68 IMAGE_REL_AMD64_SECTION f -; OBJ64-NEXT:   0x7C IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT:   0x80 IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT:   0x98 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT:   0x9C IMAGE_REL_AMD64_SECTION f  ; OBJ64-NEXT: ]  ; OBJ64:      Subsection [  ; OBJ64-NEXT:   SubSectionType: Symbols (0xF1) @@ -202,7 +224,7 @@  ; OBJ64:          DisplayName: f  ; OBJ64:          LinkageName: f  ; OBJ64:        } -; OBJ64-NEXT:   ProcEnd { +; OBJ64:        ProcEnd {  ; OBJ64:        }  ; OBJ64-NEXT: ]  ; OBJ64:       Subsection [ diff --git a/llvm/test/DebugInfo/COFF/types-array.ll b/llvm/test/DebugInfo/COFF/types-array.ll index 10ae42653fa..16298dafbd4 100644 --- a/llvm/test/DebugInfo/COFF/types-array.ll +++ b/llvm/test/DebugInfo/COFF/types-array.ll @@ -67,11 +67,8 @@  ; CHECK:       ]  ; CHECK:       VarName: a  ; CHECK:     } -; CHECK:     DefRangeRegisterRelSym { -; CHECK:       BaseRegister: EBP (0x16) -; CHECK:       HasSpilledUDTMember: No -; CHECK:       OffsetInParent: 0 -; CHECK:       BasePointerOffset: -20 +; CHECK:     DefRangeFramePointerRelSym { +; CHECK:       Offset: -20  ; CHECK:       LocalVariableAddrRange {  ; CHECK:         OffsetStart: .text+0x6  ; CHECK:         ISectStart: 0x0 diff --git a/llvm/test/DebugInfo/COFF/vframe-fpo.ll b/llvm/test/DebugInfo/COFF/vframe-fpo.ll new file mode 100644 index 00000000000..b3b71530214 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/vframe-fpo.ll @@ -0,0 +1,264 @@ +; RUN: llc < %s | FileCheck %s --check-prefix=ASM +; RUN: llc < %s -filetype=obj | llvm-readobj -codeview | FileCheck %s --check-prefix=CODEVIEW + +; This test checks that for 32-bit x86 we use VFRAME and +; S_DEFRANGE_FRAMEPOINTER_REL with the right offsets. The test has two function +; calls with different stack depths, which makes it impossible to correctly +; describe locals in memory as being ESP-relative. + +; The following source can be used with a debugger to check that locals are +; displayed correctly: +; $ cat fpo.cpp +; #if 0 +; void __attribute__((optnone)) __declspec(noinline) f(int &a, int &b) { +;   __debugbreak(); +;   a += b; +; } +; void __attribute__((optnone)) __declspec(noinline) g(int &a, int &b, int &c) { +;   __debugbreak(); +;   a += b; +;   a += c; +; } +; #endif +; void f(int &a, int &b); +; void g(int &a, int &b, int &c); +; int main() { +;   int a = 1; +;   int b = 2; +;   int c = 3; +;   f(a, b); +;   g(a, b, c); +;   return a + b + c; +; } +; $ clang -S -g -gcodeview t.cpp -emit-llvm -o vframe-fpo.ll -Os + +; ASM-LABEL: _main: +; ASM:      # %bb.0:                                # %entry +; ASM-NEXT:         pushl   %ebx +; ASM-NEXT:         .cv_fpo_pushreg %ebx +; ASM-NEXT:         pushl   %edi +; ASM-NEXT:         .cv_fpo_pushreg %edi +; ASM-NEXT:         pushl   %esi +; ASM-NEXT:         .cv_fpo_pushreg %esi +; ASM-NEXT:         subl    $12, %esp +; ASM-NEXT:         .cv_fpo_stackalloc      12 +; ASM-NEXT:         .cv_fpo_endprologue + +; Store locals. +; ASM:         movl    $1, {{.*}} +; ASM:         movl    $2, {{.*}} +; ASM:         movl    $3, {{.*}} + +; ASM that store-to-push conversion fires. +; ASM:         pushl +; ASM-NEXT:    pushl +; ASM-NEXT:    calll   "?f@@YAXAAH0@Z" +; ASM-NEXT:    addl    $8, %esp +; ASM:         pushl +; ASM-NEXT:    pushl +; ASM-NEXT:    pushl +; ASM-NEXT:    calll   "?g@@YAXAAH00@Z" + +; CODEVIEW:      CodeViewDebugInfo [ +; CODEVIEW-NEXT:   Section: .debug$S (4) +; CODEVIEW-NEXT:   Magic: 0x4 +; CODEVIEW-NEXT:   Subsection [ +; CODEVIEW-NEXT:     SubSectionType: Symbols (0xF1) +; CODEVIEW-NEXT:     SubSectionSize: 0x2F +; CODEVIEW-NEXT:     Compile3Sym { +; CODEVIEW-NEXT:       Kind: S_COMPILE3 (0x113C) +; CODEVIEW:          } +; CODEVIEW:        ] +; CODEVIEW:        Subsection [ +; CODEVIEW-NEXT:     SubSectionType: FrameData (0xF5) +; CODEVIEW-NEXT:     SubSectionSize: 0xA4 +; CODEVIEW-NEXT:     LinkageName: _main +; CODEVIEW:          FrameData { +; CODEVIEW:          } +; CODEVIEW:          FrameData { +; CODEVIEW:          } +; CODEVIEW:          FrameData { +; CODEVIEW:          } +; CODEVIEW:          FrameData { +; CODEVIEW:          } +; CODEVIEW:          FrameData { +; CODEVIEW-NEXT:       RvaStart: +; CODEVIEW-NEXT:       CodeSize: +; CODEVIEW-NEXT:       LocalSize: 0xC +; CODEVIEW-NEXT:       ParamsSize: 0x0 +; CODEVIEW-NEXT:       MaxStackSize: 0x0 +; CODEVIEW-NEXT:       PrologSize: +; CODEVIEW-NEXT:       SavedRegsSize: 0xC +; CODEVIEW-NEXT:       Flags [ (0x0) +; CODEVIEW-NEXT:       ] + +; $T0 is the CFA, the address of the return address, and our defranges are +; relative to it. +; CODEVIEW-NEXT:       FrameFunc [ +; CODEVIEW-NEXT:         $T0 .raSearch = +; CODEVIEW-NEXT:         $eip $T0 ^ = +; CODEVIEW-NEXT:         $esp $T0 4 + = +; CODEVIEW-NEXT:         $ebx $T0 4 - ^ = +; CODEVIEW-NEXT:         $edi $T0 8 - ^ = +; CODEVIEW-NEXT:         $esi $T0 12 - ^ = +; CODEVIEW-NEXT:       ] +; CODEVIEW-NEXT:     } + +; We push 16 bytes in the prologue, so our local variables are at offsets -16, +; -20, and -24. + +; CODEVIEW:      Subsection [ +; CODEVIEW-NEXT:   SubSectionType: Symbols (0xF1) +; CODEVIEW-NEXT:   SubSectionSize: 0xA2 +; CODEVIEW-NEXT:   GlobalProcIdSym { +; CODEVIEW-NEXT:     Kind: S_GPROC32_ID (0x1147) +; CODEVIEW:          DisplayName: main +; CODEVIEW:          LinkageName: _main +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   FrameProcSym { +; CODEVIEW-NEXT:     Kind: S_FRAMEPROC (0x1012) +; CODEVIEW-NEXT:     TotalFrameBytes: 0xC +; CODEVIEW-NEXT:     PaddingFrameBytes: 0x0 +; CODEVIEW-NEXT:     OffsetToPadding: 0x0 +; CODEVIEW-NEXT:     BytesOfCalleeSavedRegisters: 0xC +; CODEVIEW-NEXT:     OffsetOfExceptionHandler: 0x0 +; CODEVIEW-NEXT:     SectionIdOfExceptionHandler: 0x0 +; CODEVIEW-NEXT:     Flags [ (0x14000) +; CODEVIEW-NEXT:     ] +; CODEVIEW-NEXT:     LocalFramePtrReg: VFRAME (0x7536) +; CODEVIEW-NEXT:     ParamFramePtrReg: VFRAME (0x7536) +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   LocalSym { +; CODEVIEW-NEXT:     Kind: S_LOCAL (0x113E) +; CODEVIEW:          VarName: a +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   DefRangeFramePointerRelSym { +; CODEVIEW-NEXT:     Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142) +; CODEVIEW-NEXT:     Offset: -16 +; CODEVIEW-NEXT:     LocalVariableAddrRange { +; CODEVIEW-NEXT:       OffsetStart: +; CODEVIEW-NEXT:       ISectStart: +; CODEVIEW-NEXT:       Range: +; CODEVIEW-NEXT:     } +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   LocalSym { +; CODEVIEW-NEXT:     Kind: S_LOCAL (0x113E) +; CODEVIEW:          VarName: b +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   DefRangeFramePointerRelSym { +; CODEVIEW-NEXT:     Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142) +; CODEVIEW-NEXT:     Offset: -20 +; CODEVIEW-NEXT:     LocalVariableAddrRange { +; CODEVIEW-NEXT:       OffsetStart: +; CODEVIEW-NEXT:       ISectStart: +; CODEVIEW-NEXT:       Range: +; CODEVIEW-NEXT:     } +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   LocalSym { +; CODEVIEW-NEXT:     Kind: S_LOCAL (0x113E) +; CODEVIEW:          VarName: c +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   DefRangeFramePointerRelSym { +; CODEVIEW-NEXT:     Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142) +; CODEVIEW-NEXT:     Offset: -24 +; CODEVIEW-NEXT:     LocalVariableAddrRange { +; CODEVIEW-NEXT:       OffsetStart: +; CODEVIEW-NEXT:       ISectStart: +; CODEVIEW-NEXT:       Range: +; CODEVIEW-NEXT:     } +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT:   ProcEnd { +; CODEVIEW-NEXT:     Kind: S_PROC_ID_END (0x114F) +; CODEVIEW-NEXT:   } +; CODEVIEW-NEXT: ] + + +; ModuleID = 'fpo.cpp' +source_filename = "fpo.cpp" +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc19.14.26433" + +; Function Attrs: norecurse optsize +define dso_local i32 @main() local_unnamed_addr #0 !dbg !8 { +entry: +  %a = alloca i32, align 4 +  %b = alloca i32, align 4 +  %c = alloca i32, align 4 +  %0 = bitcast i32* %a to i8*, !dbg !16 +  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #4, !dbg !16 +  call void @llvm.dbg.declare(metadata i32* %a, metadata !13, metadata !DIExpression()), !dbg !16 +  store i32 1, i32* %a, align 4, !dbg !16, !tbaa !17 +  %1 = bitcast i32* %b to i8*, !dbg !21 +  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %1) #4, !dbg !21 +  call void @llvm.dbg.declare(metadata i32* %b, metadata !14, metadata !DIExpression()), !dbg !21 +  store i32 2, i32* %b, align 4, !dbg !21, !tbaa !17 +  %2 = bitcast i32* %c to i8*, !dbg !22 +  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %2) #4, !dbg !22 +  call void @llvm.dbg.declare(metadata i32* %c, metadata !15, metadata !DIExpression()), !dbg !22 +  store i32 3, i32* %c, align 4, !dbg !22, !tbaa !17 +  call void @"?f@@YAXAAH0@Z"(i32* nonnull dereferenceable(4) %a, i32* nonnull dereferenceable(4) %b) #5, !dbg !23 +  call void @"?g@@YAXAAH00@Z"(i32* nonnull dereferenceable(4) %a, i32* nonnull dereferenceable(4) %b, i32* nonnull dereferenceable(4) %c) #5, !dbg !24 +  %3 = load i32, i32* %a, align 4, !dbg !25, !tbaa !17 +  %4 = load i32, i32* %b, align 4, !dbg !25, !tbaa !17 +  %add = add nsw i32 %4, %3, !dbg !25 +  %5 = load i32, i32* %c, align 4, !dbg !25, !tbaa !17 +  %add1 = add nsw i32 %add, %5, !dbg !25 +  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2) #4, !dbg !26 +  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1) #4, !dbg !26 +  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #4, !dbg !26 +  ret i32 %add1, !dbg !25 +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 + +; Function Attrs: optsize +declare dso_local void @"?f@@YAXAAH0@Z"(i32* dereferenceable(4), i32* dereferenceable(4)) local_unnamed_addr #3 + +; Function Attrs: optsize +declare dso_local void @"?g@@YAXAAH00@Z"(i32* dereferenceable(4), i32* dereferenceable(4), i32* dereferenceable(4)) local_unnamed_addr #3 + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1 + +attributes #0 = { norecurse optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { argmemonly nounwind } +attributes #2 = { nounwind readnone speculatable } +attributes #3 = { optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } +attributes #5 = { optsize } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "fpo.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "d0bb7e43f4e54936a94da008319a7de3") +!2 = !{} +!3 = !{i32 1, !"NumRegisterParameters", i32 0} +!4 = !{i32 2, !"CodeView", i32 1} +!5 = !{i32 2, !"Debug Info Version", i32 3} +!6 = !{i32 1, !"wchar_size", i32 2} +!7 = !{!"clang version 8.0.0 "} +!8 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !9, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12) +!9 = !DISubroutineType(types: !10) +!10 = !{!11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !{!13, !14, !15} +!13 = !DILocalVariable(name: "a", scope: !8, file: !1, line: 15, type: !11) +!14 = !DILocalVariable(name: "b", scope: !8, file: !1, line: 16, type: !11) +!15 = !DILocalVariable(name: "c", scope: !8, file: !1, line: 17, type: !11) +!16 = !DILocation(line: 15, scope: !8) +!17 = !{!18, !18, i64 0} +!18 = !{!"int", !19, i64 0} +!19 = !{!"omnipotent char", !20, i64 0} +!20 = !{!"Simple C++ TBAA"} +!21 = !DILocation(line: 16, scope: !8) +!22 = !DILocation(line: 17, scope: !8) +!23 = !DILocation(line: 18, scope: !8) +!24 = !DILocation(line: 19, scope: !8) +!25 = !DILocation(line: 20, scope: !8) +!26 = !DILocation(line: 21, scope: !8) diff --git a/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll b/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll index 53ceeb1751b..c28485c776c 100644 --- a/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll +++ b/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll @@ -59,6 +59,12 @@  ; OBJ:   Kind: S_GPROC32_ID (0x1147)  ; OBJ:   DisplayName: f  ; OBJ: } +; OBJ: FrameProcSym { +; OBJ:   Kind: S_FRAMEPROC (0x1012) +; OBJ:   TotalFrameBytes: 0x8 +; OBJ:   LocalFramePtrReg: VFRAME (0x7536) +; OBJ:   ParamFramePtrReg: VFRAME (0x7536) +; OBJ: }  ; OBJ: LocalSym {  ; OBJ:   Type: NonTrivial (0x1007)  ; OBJ:   Flags [ (0x1) @@ -66,9 +72,8 @@  ; OBJ:   ]  ; OBJ:   VarName: a  ; OBJ: } -; OBJ: DefRangeRegisterRelSym { -; OBJ:   BaseRegister: ESP (0x15) -; OBJ:   BasePointerOffset: 12 +; OBJ: DefRangeFramePointerRelSym { +; OBJ:   Offset: 4  ; OBJ: }  ; OBJ: LocalSym {  ; OBJ:   Type: int (0x74) @@ -77,9 +82,8 @@  ; OBJ:   ]  ; OBJ:   VarName: b  ; OBJ: } -; OBJ: DefRangeRegisterRelSym { -; OBJ:   BaseRegister: ESP (0x15) -; OBJ:   BasePointerOffset: 16 +; OBJ: DefRangeFramePointerRelSym { +; OBJ:   Offset: 8  ; OBJ: }  ; FIXME: Retain unused.  ; OBJ: LocalSym { @@ -89,9 +93,8 @@  ; OBJ:   ]  ; OBJ:   VarName: c  ; OBJ: } -; OBJ: DefRangeRegisterRelSym { -; OBJ:   BaseRegister: ESP (0x15) -; OBJ:   BasePointerOffset: 24 +; OBJ: DefRangeFramePointerRelSym { +; OBJ:   Offset: 16  ; OBJ: }  ; OBJ-LABEL: ProcEnd {  ; OBJ: } diff --git a/llvm/test/MC/ARM/coff-debugging-secrel.ll b/llvm/test/MC/ARM/coff-debugging-secrel.ll index 0cfd5105eb7..dbd251adae1 100644 --- a/llvm/test/MC/ARM/coff-debugging-secrel.ll +++ b/llvm/test/MC/ARM/coff-debugging-secrel.ll @@ -44,8 +44,8 @@ entry:  ; CHECK-MSVC:   Section {{.*}} .debug$S {  ; CHECK-MSVC:     0x64 IMAGE_REL_ARM_SECREL function  ; CHECK-MSVC:     0x68 IMAGE_REL_ARM_SECTION function -; CHECK-MSVC:     0x80 IMAGE_REL_ARM_SECREL function -; CHECK-MSVC:     0x84 IMAGE_REL_ARM_SECTION function +; CHECK-MSVC:     0xA0 IMAGE_REL_ARM_SECREL function +; CHECK-MSVC:     0xA4 IMAGE_REL_ARM_SECTION function  ; CHECK-MSVC:   }  ; CHECK-MSVC: ]  | 

