[llvm] r343543 - [codeview] Emit S_FRAMEPROC and use S_DEFRANGE_FRAMEPOINTER_REL

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 1 14:59:46 PDT 2018


Author: rnk
Date: Mon Oct  1 14:59:45 2018
New Revision: 343543

URL: http://llvm.org/viewvc/llvm-project?rev=343543&view=rev
Log:
[codeview] Emit S_FRAMEPROC and use S_DEFRANGE_FRAMEPOINTER_REL

Summary:
Before this change, LLVM would always describe locals on the stack as
being relative to some specific register, RSP, ESP, EBP, ESI, etc.
Variables in stack memory are pretty common, so there is a special
S_DEFRANGE_FRAMEPOINTER_REL symbol for them. This change uses it to
reduce the size of our debug info.

On top of the size savings, there are cases on 32-bit x86 where local
variables are addressed from ESP, but ESP changes across the function.
Unlike in DWARF, there is no FPO data to describe the stack adjustments
made to push arguments onto the stack and pop them off after the call,
which makes it hard for the debugger to find the local variables in
frames further up the stack.

To handle this, CodeView has a special VFRAME register, which
corresponds to the $T0 variable set by our FPO data in 32-bit.  Offsets
to local variables are instead relative to this value.

This is part of PR38857.

Reviewers: hans, zturner, javed.absar

Subscribers: aprantl, hiraditya, JDevlieghere, llvm-commits

Differential Revision: https://reviews.llvm.org/D52217

Added:
    llvm/trunk/test/DebugInfo/COFF/frameproc-flags.ll
    llvm/trunk/test/DebugInfo/COFF/vframe-fpo.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h
    llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
    llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp
    llvm/trunk/lib/CodeGen/MIRPrinter.cpp
    llvm/trunk/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
    llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
    llvm/trunk/test/CodeGen/MIR/Generic/frame-info.mir
    llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir
    llvm/trunk/test/DebugInfo/COFF/asm.ll
    llvm/trunk/test/DebugInfo/COFF/local-variables.ll
    llvm/trunk/test/DebugInfo/COFF/multifile.ll
    llvm/trunk/test/DebugInfo/COFF/multifunction.ll
    llvm/trunk/test/DebugInfo/COFF/pieces.ll
    llvm/trunk/test/DebugInfo/COFF/simple.ll
    llvm/trunk/test/DebugInfo/COFF/types-array.ll
    llvm/trunk/test/DebugInfo/X86/dbg-declare-inalloca.ll
    llvm/trunk/test/MC/ARM/coff-debugging-secrel.ll

Modified: llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h Mon Oct  1 14:59:45 2018
@@ -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<Machine
     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);

Modified: llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h Mon Oct  1 14:59:45 2018
@@ -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

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h Mon Oct  1 14:59:45 2018
@@ -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,

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h Mon Oct  1 14:59:45 2018
@@ -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

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Mon Oct  1 14:59:45 2018
@@ -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
     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 Na
   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::emitCompilerInformat
   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(
 
   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::emitDebugInfoForFunc
     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(
 }
 
 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(co
   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::emitDeferredComplete
   }
 }
 
-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::emitLocalVariableLis
     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(co
   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(con
   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);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Mon Oct  1 14:59:45 2018
@@ -54,6 +54,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   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 CodeViewDe
     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 CodeViewDe
   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,

Modified: llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp Mon Oct  1 14:59:45 2018
@@ -580,6 +580,7 @@ bool MIRParserImpl::initializeFrameInfo(
   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);

Modified: llvm/trunk/lib/CodeGen/MIRPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRPrinter.cpp?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRPrinter.cpp Mon Oct  1 14:59:45 2018
@@ -328,6 +328,8 @@ void MIRPrinter::convert(ModuleSlotTrack
   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();

Modified: llvm/trunk/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp Mon Oct  1 14:59:45 2018
@@ -471,3 +471,75 @@ Error SymbolRecordMapping::visitKnownRec
 
   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;
+}

Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Mon Oct  1 14:59:45 2018
@@ -1983,6 +1983,7 @@ bool X86FrameLowering::assignCalleeSaved
   }
 
   X86FI->setCalleeSavedFrameSize(CalleeSavedFrameSize);
+  MFI.setCVBytesOfCalleeSavedRegisters(CalleeSavedFrameSize);
 
   // Assign slots for XMMs.
   for (unsigned i = CSI.size(); i != 0; --i) {

Modified: llvm/trunk/test/CodeGen/MIR/Generic/frame-info.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/Generic/frame-info.mir?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/Generic/frame-info.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/Generic/frame-info.mir Mon Oct  1 14:59:45 2018
@@ -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

Modified: llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/diexpr-win32.mir Mon Oct  1 14:59:45 2018
@@ -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)

Modified: llvm/trunk/test/DebugInfo/COFF/asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/asm.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/asm.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/asm.ll Mon Oct  1 14:59:45 2018
@@ -99,7 +99,7 @@
 ; OBJ64:          DisplayName: f
 ; OBJ64:          LinkageName: f
 ; OBJ64:        }
-; OBJ64-NEXT:   ProcEnd {
+; OBJ64:        ProcEnd {
 ; OBJ64:        }
 ; OBJ64-NEXT: ]
 ; OBJ64:      FunctionLineTable [

Added: llvm/trunk/test/DebugInfo/COFF/frameproc-flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/frameproc-flags.ll?rev=343543&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/frameproc-flags.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/frameproc-flags.ll Mon Oct  1 14:59:45 2018
@@ -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 at 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] }
+
+ at 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 at Z", !dbg !62
+}
+
+; Function Attrs: inlinehint nounwind readnone
+define internal i32 @"?is_marked_inline@@YAHHH at 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 at 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 at 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 at 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 at 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)

Modified: llvm/trunk/test/DebugInfo/COFF/local-variables.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/local-variables.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/local-variables.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/local-variables.ll Mon Oct  1 14:59:45 2018
@@ -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

Modified: llvm/trunk/test/DebugInfo/COFF/multifile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifile.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/multifile.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/multifile.ll Mon Oct  1 14:59:45 2018
@@ -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 [

Modified: llvm/trunk/test/DebugInfo/COFF/multifunction.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifunction.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/multifunction.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/multifunction.ll Mon Oct  1 14:59:45 2018
@@ -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)

Modified: llvm/trunk/test/DebugInfo/COFF/pieces.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/pieces.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/pieces.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/pieces.ll Mon Oct  1 14:59:45 2018
@@ -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:       }

Modified: llvm/trunk/test/DebugInfo/COFF/simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/simple.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/simple.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/simple.ll Mon Oct  1 14:59:45 2018
@@ -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 [

Modified: llvm/trunk/test/DebugInfo/COFF/types-array.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-array.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-array.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/types-array.ll Mon Oct  1 14:59:45 2018
@@ -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

Added: llvm/trunk/test/DebugInfo/COFF/vframe-fpo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/vframe-fpo.ll?rev=343543&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/vframe-fpo.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/vframe-fpo.ll Mon Oct  1 14:59:45 2018
@@ -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 at Z"
+; ASM-NEXT:    addl    $8, %esp
+; ASM:         pushl
+; ASM-NEXT:    pushl
+; ASM-NEXT:    pushl
+; ASM-NEXT:    calll   "?g@@YAXAAH00 at 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 at Z"(i32* nonnull dereferenceable(4) %a, i32* nonnull dereferenceable(4) %b) #5, !dbg !23
+  call void @"?g@@YAXAAH00 at 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 at Z"(i32* dereferenceable(4), i32* dereferenceable(4)) local_unnamed_addr #3
+
+; Function Attrs: optsize
+declare dso_local void @"?g@@YAXAAH00 at 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)

Modified: llvm/trunk/test/DebugInfo/X86/dbg-declare-inalloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dbg-declare-inalloca.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dbg-declare-inalloca.ll (original)
+++ llvm/trunk/test/DebugInfo/X86/dbg-declare-inalloca.ll Mon Oct  1 14:59:45 2018
@@ -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: }

Modified: llvm/trunk/test/MC/ARM/coff-debugging-secrel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/coff-debugging-secrel.ll?rev=343543&r1=343542&r2=343543&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/coff-debugging-secrel.ll (original)
+++ llvm/trunk/test/MC/ARM/coff-debugging-secrel.ll Mon Oct  1 14:59:45 2018
@@ -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: ]
 




More information about the llvm-commits mailing list