diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -14,6 +14,7 @@ #define LLVM_CODEGEN_MACHINEFRAMEINFO_H #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/Register.h" #include "llvm/Support/Alignment.h" #include diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -63,6 +63,12 @@ createMachineFunctionPrinterPass(raw_ostream &OS, const std::string &Banner =""); + /// StackFramePrinter pass - This pass prints out the machine function's + /// stack frame to the given stream as a debugging tool. + MachineFunctionPass * + createStackFramePrinterPass(raw_ostream &OS, + const std::string &Banner =""); + /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream /// using the MIR serialization format. MachineFunctionPass *createPrintMIRPass(raw_ostream &OS); @@ -260,6 +266,10 @@ /// It merges disjoint allocas to reduce the stack size. extern char &StackColoringID; + /// StackFramePrinter - This pass prints the stack frame layout and variable + /// mappings. + extern char &StackFramePrinterPassID; + /// IfConverter - This pass performs machine code if conversion. extern char &IfConverterID; diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -402,6 +402,7 @@ void initializeSpeculativeExecutionLegacyPassPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); void initializeStackColoringPass(PassRegistry&); +void initializeStackFramePrinterPassPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackSafetyGlobalInfoWrapperPassPass(PassRegistry &); diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -207,6 +207,7 @@ SpillPlacement.cpp SplitKit.cpp StackColoring.cpp + StackFramePrinterPass.cpp StackMapLivenessAnalysis.cpp StackMaps.cpp StackProtector.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -115,6 +115,7 @@ initializeSjLjEHPreparePass(Registry); initializeSlotIndexesPass(Registry); initializeStackColoringPass(Registry); + initializeStackFramePrinterPassPass(Registry); initializeStackMapLivenessPass(Registry); initializeStackProtectorPass(Registry); initializeStackSlotColoringPass(Registry); diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp --- a/llvm/lib/CodeGen/MachineFrameInfo.cpp +++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp @@ -20,9 +20,12 @@ #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/Config/llvm-config.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include +#include +#include #define DEBUG_TYPE "codegen" diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -51,6 +51,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/ModuleSlotTracker.h" #include "llvm/InitializePasses.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Pass.h" @@ -289,6 +290,9 @@ if (StackSize > Threshold) { DiagnosticInfoStackSize DiagStackSize(F, StackSize, Threshold, DS_Warning); F.getContext().diagnose(DiagStackSize); + //TODO: print stats here about stack usage: + // How much total memory + // What % are locals vs spills } ORE->emit([&]() { return MachineOptimizationRemarkAnalysis(DEBUG_TYPE, "StackSize", diff --git a/llvm/lib/CodeGen/StackFramePrinterPass.cpp b/llvm/lib/CodeGen/StackFramePrinterPass.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/StackFramePrinterPass.cpp @@ -0,0 +1,254 @@ +//===-- MachineFunctionPrinterPass.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// StackFramePrinterPass implementation. Prints a textual representation of +// the stack frame. When possible it prints the values that occupy a stack slot +// using any available debug information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/PrintPasses.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + +using namespace llvm; + +namespace { + +constexpr int OffsetWidth = 4 + 7; +constexpr int SpillWidth = 5; +constexpr int AlignWidth = 9; +constexpr int SizeWidth = 10; + +constexpr size_t MaxLine = + std::min(75, OffsetWidth + SpillWidth + AlignWidth + SizeWidth + 3); + +/// StackFramePrinterPass - This is a pass to dump the stack frame of a +/// MachineFunction. +/// +struct StackFramePrinterPass : public MachineFunctionPass { + using SlotDbgMap = + SmallDenseMap>; + static char ID; + + raw_ostream &OS; + const std::string Banner; + + struct SlotData { + int Slot; + int Size; + int Align; + int Offset; + bool IsSpillSlot; + bool Fixed; + }; + + StackFramePrinterPass() : MachineFunctionPass(ID), OS(dbgs()) {} + StackFramePrinterPass(raw_ostream &OS, const std::string &Banner) + : MachineFunctionPass(ID), OS(OS), Banner(Banner) {} + + StringRef getPassName() const override { return "StackFrame Printer"; } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) override { + if (!isFunctionInPrintList(MF.getName())) + return false; + + OS << "# " << Banner << ": " << MF.getName() << "\n"; + + auto SlotMap = genSlotDbgMapping(MF); + printFrame(MF, OS, SlotMap); + + return false; + } + + std::string genFieldInt(int Width, int I) const { + std::stringstream SS; + SS.setf(std::ios_base::left); + SS << std::setw(Width) << I; + return SS.str(); + } + + std::string genFieldString(int Width, std::string S) const { + std::stringstream SS; + SS.setf(std::ios_base::left); + SS << std::setw(Width) << S; + return SS.str(); + } + + std::string genFieldOffset(int I) const { + std::stringstream SS; + SS.setf(std::ios_base::left); + SS << "[SP"; + const auto *Op = (I < 0) ? "" : "+"; + SS << Op << I << "]"; + return SS.str(); + } + + std::string genBody(int Idx, SlotData &D) const { + std::stringstream SS; + SS.setf(std::ios_base::left); + + SS << std::setw(OffsetWidth) << genFieldOffset(D.Offset) << " "; + SS << genFieldString(SpillWidth, D.IsSpillSlot ? "Spill" : "") << " "; + SS << genFieldInt(AlignWidth, D.Align) << " "; + SS << genFieldInt(SizeWidth, D.Size); + return SS.str(); + }; + + std::string genHeader() const { + std::stringstream SS; + SS.setf(std::ios_base::left); + SS << genFieldString(OffsetWidth, "Offset") << " "; + SS << genFieldString(SpillWidth, "") << " "; + SS << genFieldString(AlignWidth, "Align") << " "; + SS << genFieldString(SizeWidth, "Size"); + return SS.str(); + }; + + void printSourceLoc(raw_ostream &OS, const llvm::DILocalVariable *N) const { + OS << " " << N->getName().str() << " @ " << N->getFilename() << ":" + << N->getLine(); + OS << "\n"; + } + + void printRow(raw_ostream &OS, std::string S) const { + std::stringstream SS; + SS.setf(std::ios_base::left); + SS << std::setw(MaxLine) << S; + OS << " " << SS.str() << " \n"; + }; + + void printFrame(const MachineFunction &MF, raw_ostream &OS, + SlotDbgMap &SlotMap) const { + auto &MFI = MF.getFrameInfo(); + + if (!MFI.hasStackObjects()) + return; + + const TargetFrameLowering *FI = MF.getSubtarget().getFrameLowering(); + int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0); + + std::vector SlotInfo; + SmallDenseMap SlotOffsetMap; + auto NumObj = MFI.getNumObjects(); + auto ObjBeg = MFI.getObjectIndexBegin(); + auto ObjEnd = MFI.getObjectIndexEnd(); + int NumFixed = MFI.getNumFixedObjects(); + + SlotInfo.reserve(NumObj); + SlotOffsetMap.reserve(NumObj); + // initialize slot info + for (auto Idx = ObjBeg, EndIdx = ObjEnd; Idx != EndIdx; ++Idx) { + SlotData D; + uint64_t Size = MFI.getObjectSize(Idx); + + // This is a dead slot, so skip it + if (Size == ~0ULL) { + continue; + } + + D.Slot = (int)(Idx); + // If Size == 0, then its a variable size object... + D.Size = Size; + D.Align = MFI.getObjectAlign(Idx).value(); + D.Fixed = (Idx < NumFixed); + D.IsSpillSlot = MFI.isSpillSlotObjectIndex(Idx); + D.Offset = MFI.getObjectOffset(Idx) - ValOffset; + SlotInfo.push_back(D); + SlotOffsetMap[D.Slot] = D.Offset; + } + + // sort the ordering, to match the actual layout in memory + std::sort(SlotInfo.begin(), SlotInfo.end(), + [](SlotData &A, SlotData &B) { return A.Offset > B.Offset; }); + + printRow(OS, genHeader()); + + int Idx = 0; + for (auto L : SlotInfo) { + std::stringstream SS; + auto Body = genBody(Idx++, L); + printRow(OS, Body); + for (auto *N : SlotMap[L.Slot]) + printSourceLoc(OS, N); + } + OS << "\n"; + } + + // We need to generate a mapping of slots to the values that are stored to + // them This infomation is lost by the time we need to print out the frame, so + // we reconstruct it here by walking the CFG, and generating the mapping. + SlotDbgMap genSlotDbgMapping(MachineFunction &MF) { + SlotDbgMap SlotDebugMap; + SmallVector Dbg; + + // add variables to the map + for (auto &DI : MF.getVariableDbgInfo()) { + SlotDebugMap[DI.Slot].insert(DI.Var); + } + + // Then add all the spills that have debug data + for (auto &MBB : MF) { + for (auto &MI : MBB) { + if (MI.getNumMemOperands() == 0) + continue; + for (MachineMemOperand *MO : MI.memoperands()) { + if (!MO->isStore()) + continue; + auto *FI = dyn_cast_or_null( + MO->getPseudoValue()); + if (!FI) + continue; + auto FrameIdx = FI->getFrameIndex(); + Dbg.clear(); + MI.collectDebugValues(Dbg); + + for (auto *MI : Dbg) + SlotDebugMap[FrameIdx].insert(MI->getDebugVariable()); + } + } + } + + return SlotDebugMap; + } +}; + +char StackFramePrinterPass::ID = 0; +} // namespace + +char &llvm::StackFramePrinterPassID = StackFramePrinterPass::ID; +INITIALIZE_PASS(StackFramePrinterPass, "stackframe-printer", + "Stack Frame Printer", false, false) + +namespace llvm { +/// Returns a newly-created MachineFunction Printer pass. The +/// default banner is empty. +/// +MachineFunctionPass *createStackFramePrinterPass(raw_ostream &OS, + const std::string &Banner) { + return new StackFramePrinterPass(OS, Banner); +} + +} // namespace llvm diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -159,6 +159,10 @@ PrintAfterISel("print-after-isel", cl::init(false), cl::Hidden, cl::desc("Print machine instrs after ISel")); +static cl::opt + PrintStackFrame("print-stack-frame", cl::init(false), cl::Hidden, + cl::desc("Print Stack Frame")); + static cl::opt EnableGlobalISelAbort( "global-isel-abort", cl::Hidden, cl::desc("Enable abort calls when \"global\" instruction selection " @@ -1297,6 +1301,9 @@ if (!DisableCFIFixup && TM->Options.EnableCFIFixup) addPass(createCFIFixup()); + if(PrintStackFrame) + PM->add(createStackFramePrinterPass(dbgs(), "Stack Layout")); + // Add passes that directly emit MI after all other MI passes. addPreEmitPass2(); diff --git a/llvm/test/CodeGen/X86/stack-frame-printer.ll b/llvm/test/CodeGen/X86/stack-frame-printer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/stack-frame-printer.ll @@ -0,0 +1,107 @@ +; Test basic output of the -print-stack-frame pass + +; RUN: llc -mcpu=corei7 -O1 -print-stack-frame < %s 2>&1 >/dev/null | FileCheck %s +; RUN: llc -mcpu=corei7 -O0 -print-stack-frame < %s 2>&1 >/dev/null | FileCheck %s --check-prefix=NO_COLORING + + +; CHECK: Offset{{.*}}Align{{.*}}Size +; CHECK: [SP-88]{{.*}}16{{.*}}80 +; CHECK: buffer @ frame-diags.c:30 +; NO_COLORING: [SP-168]{{.*}}16{{.*}}80 +; CHECK: buffer2 @ frame-diags.c:33 + +; ModuleID = 'frame-diags.c' +source_filename = "frame-diags.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define dso_local void @stackSizeWarning() local_unnamed_addr #0 !dbg !9 { +entry: + %buffer = alloca [80 x i8], align 16 + %buffer2 = alloca [80 x i8], align 16 + call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %buffer) #5, !dbg !24 + call void @llvm.dbg.declare(metadata ptr %buffer, metadata !13, metadata !DIExpression()), !dbg !25 + call void @doIt(ptr noundef nonnull %buffer) #5, !dbg !26 + call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %buffer) #5, !dbg !27 + call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %buffer2) #5, !dbg !28 + call void @llvm.dbg.declare(metadata ptr %buffer2, metadata !19, metadata !DIExpression()), !dbg !29 + call void @llvm.dbg.value(metadata i32 0, metadata !20, metadata !DIExpression()), !dbg !30 + call void @llvm.dbg.value(metadata i64 1, metadata !22, metadata !DIExpression()), !dbg !30 + call void @doIt(ptr noundef nonnull %buffer2) #5, !dbg !31 + %call = call i32 @getNum(i64 noundef 0) #5, !dbg !32 + %call2 = call i32 @getNum(i64 noundef 1) #5, !dbg !33 + call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %buffer2) #5, !dbg !34 + ret void, !dbg !34 +} + +; Function Attrs: argmemonly mustprogress nocallback nofree nosync nounwind willreturn +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 + +declare !dbg !35 void @doIt(ptr noundef) local_unnamed_addr #3 + +; Function Attrs: argmemonly mustprogress nocallback nofree nosync nounwind willreturn +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 + +declare !dbg !40 i32 @getNum(i64 noundef) local_unnamed_addr #3 + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #4 + +attributes #0 = { nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { argmemonly mustprogress nocallback nofree nosync nounwind willreturn } +attributes #2 = { mustprogress nocallback nofree nosync nounwind readnone speculatable willreturn } +attributes #3 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #4 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +attributes #5 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Fuchsia clang version 16.0.0 (git@github.com:llvm/llvm-project.git bb51a99e67747be81c9b523fd5ddcc8bf91a1ffb)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "frame-diags.c", directory: "/usr/local/google/home/paulkirth/llvm-sysroot/clang/test/Frontend", checksumkind: CSK_MD5, checksum: "01b5d69ce5387b02de2d1191b28a0b7f") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{!"Fuchsia clang version 16.0.0 (git@github.com:llvm/llvm-project.git bb51a99e67747be81c9b523fd5ddcc8bf91a1ffb)"} +!9 = distinct !DISubprogram(name: "stackSizeWarning", scope: !1, file: !1, line: 28, type: !10, scopeLine: 28, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!10 = !DISubroutineType(types: !11) +!11 = !{null} +!12 = !{!13, !19, !20, !22} +!13 = !DILocalVariable(name: "buffer", scope: !14, file: !1, line: 30, type: !15) +!14 = distinct !DILexicalBlock(scope: !9, file: !1, line: 29, column: 3) +!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !16, size: 640, elements: !17) +!16 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!17 = !{!18} +!18 = !DISubrange(count: 80) +!19 = !DILocalVariable(name: "buffer2", scope: !9, file: !1, line: 33, type: !15) +!20 = !DILocalVariable(name: "a", scope: !9, file: !1, line: 34, type: !21) +!21 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!22 = !DILocalVariable(name: "b", scope: !9, file: !1, line: 35, type: !23) +!23 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) +!24 = !DILocation(line: 30, column: 5, scope: !14) +!25 = !DILocation(line: 30, column: 10, scope: !14) +!26 = !DILocation(line: 31, column: 5, scope: !14) +!27 = !DILocation(line: 32, column: 3, scope: !9) +!28 = !DILocation(line: 33, column: 3, scope: !9) +!29 = !DILocation(line: 33, column: 8, scope: !9) +!30 = !DILocation(line: 0, scope: !9) +!31 = !DILocation(line: 36, column: 3, scope: !9) +!32 = !DILocation(line: 38, column: 3, scope: !9) +!33 = !DILocation(line: 39, column: 3, scope: !9) +!34 = !DILocation(line: 40, column: 1, scope: !9) +!35 = !DISubprogram(name: "doIt", scope: !1, file: !1, line: 21, type: !36, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !39) +!36 = !DISubroutineType(types: !37) +!37 = !{null, !38} +!38 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64) +!39 = !{} +!40 = !DISubprogram(name: "getNum", scope: !1, file: !1, line: 23, type: !41, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !39) +!41 = !DISubroutineType(types: !42) +!42 = !{!21, !23} diff --git a/llvm/test/CodeGen/X86/stack-frame-printer2.ll b/llvm/test/CodeGen/X86/stack-frame-printer2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/stack-frame-printer2.ll @@ -0,0 +1,764 @@ + +; RUN: llc %s -print-stack-frame -o /dev/null --march=x86 -mcpu=i386 2>&1 | FileCheck %s --check-prefix=BOTH --check-prefix=DEBUG +; RUN: opt %s -strip -S | llc -print-stack-frame -o /dev/null --march=x86 -mcpu=i386 2>&1 | FileCheck %s --check-prefix=BOTH --check-prefix=STRIPPED + + +; BOTH: # Stack Layout: cleanup_array +; BOTH: Offset{{.*}}Align{{.*}}Size +; BOTH: [SP+4]{{.+}}16{{.+}}4 +; DEBUG: a @ dot.c:13 +; STRIPPED-NOT: a @ dot.c:13 +; BOTH: [SP-4]{{.+}}Spill 8{{.+}}4 + +; BOTH: # Stack Layout: cleanup_result +; BOTH: Offset{{.+}}Align{{.+}}Size +; BOTH: [SP+4]{{.+}}16{{.+}}4 +; DEBUG: res @ dot.c:21 +; STRIPPED-NOT: res @ dot.c:21 +; BOTH: [SP-4]{{.+}}Spill 8{{.+}}4 + +; BOTH: # Stack Layout: do_work +; BOTH: Offset{{.+}}Align{{.+}}Size +; BOTH: [SP+12]{{.+}}8{{.+}}4 +; DEBUG: out @ dot.c:32 +; STRIPPED-NOT: out @ dot.c:32 +; BOTH: [SP+8]{{.+}}4{{.+}}4 +; BOTH: [SP+4]{{.+}}16{{.+}}4 +; DEBUG: A @ dot.c:32 +; STRIPPED-NOT: A @ dot.c:32 +; BOTH: [SP-4]{{.+}}Spill 8{{.+}}4 +; BOTH: [SP-12]{{.+}}8{{.+}}4 +; DEBUG: AB @ dot.c:38 +; STRIPPED-NOT: AB @ dot.c:38 +; BOTH: [SP-16]{{.+}}4{{.+}}4 +; DEBUG: i @ dot.c:55 +; STRIPPED-NOT: i @ dot.c:55 +; BOTH: [SP-20]{{.+}}8{{.+}}4 +; DEBUG: B @ dot.c:32 +; STRIPPED-NOT: B @ dot.c:32 +; BOTH: [SP-24]{{.+}}4{{.+}}4 +; DEBUG: len @ dot.c:37 +; STRIPPED-NOT: len @ dot.c:37 +; BOTH: [SP-28]{{.+}}4{{.+}}4 +; BOTH: [SP-32]{{.+}}4{{.+}}4 +; DEBUG: sum @ dot.c:54 +; STRIPPED-NOT: sum @ dot.c:54 + +; BOTH: # Stack Layout: gen_array +; BOTH: Offset{{.+}}Align{{.+}}Size +; BOTH: [SP+4]{{.+}}16{{.+}}4 +; DEBUG: size @ dot.c:62 +; STRIPPED-NOT: size @ dot.c:62 +; BOTH: [SP-4]{{.+}}Spill 8{{.+}}4 +; BOTH: [SP-12]{{.+}}8{{.+}}4 +; DEBUG: res @ dot.c:65 +; STRIPPED-NOT: res @ dot.c:65 +; BOTH: [SP-16]{{.+}}4{{.+}}4 +; DEBUG: i @ dot.c:69 +; STRIPPED-NOT: i @ dot.c:69 +; BOTH: [SP-20]{{.+}}8 4 + +; BOTH: # Stack Layout: caller +; BOTH: Offset{{.+}}Align{{.+}}Size +; BOTH: [SP-4]{{.+}}Spill 8{{.+}}4 +; BOTH: [SP-12]{{.+}}8{{.+}}4 +; DEBUG: res @ dot.c:80 +; STRIPPED-NOT: res @ dot.c:80 +; BOTH: [SP-20]{{.+}}8{{.+}}4 +; DEBUG: B @ dot.c:79 +; STRIPPED-NOT: B @ dot.c:79 +; BOTH: [SP-28]{{.+}}8{{.+}}4 +; DEBUG: A @ dot.c:78 +; STRIPPED-NOT: A @ dot.c:78 +; BOTH: [SP-32]{{.+}}4{{.+}}4 +; DEBUG: ret @ dot.c:81 +; STRIPPED-NOT: ret @ dot.c:81 +; BOTH: [SP-36]{{.+}}4{{.+}}4 +; BOTH: [SP-40]{{.+}}4{{.+}}4 +; DEBUG: err @ dot.c:83 +; STRIPPED-NOT: err @ dot.c:83 +; BOTH: [SP-44]{{.+}}4{{.+}}4 +; DEBUG: size @ dot.c:77 +; STRIPPED-NOT: size @ dot.c:77 + + + + +; ModuleID = 'dot.c' +source_filename = "dot.c" + +%struct.Array = type { ptr, i32 } +%struct.Result = type { ptr, i32 } + +; Function Attrs: noinline nounwind uwtable +define dso_local void @cleanup_array(ptr noundef %0) #0 !dbg !24 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8 + call void @llvm.dbg.declare(metadata ptr %2, metadata !28, metadata !DIExpression()), !dbg !29 + %3 = load ptr, ptr %2, align 8, !dbg !30 + %4 = icmp ne ptr %3, null, !dbg !30 + br i1 %4, label %6, label %5, !dbg !32 + +5: ; preds = %1 + br label %16, !dbg !33 + +6: ; preds = %1 + %7 = load ptr, ptr %2, align 8, !dbg !34 + %8 = getelementptr inbounds %struct.Array, ptr %7, i32 0, i32 0, !dbg !36 + %9 = load ptr, ptr %8, align 8, !dbg !36 + %10 = icmp ne ptr %9, null, !dbg !34 + br i1 %10, label %12, label %11, !dbg !37 + +11: ; preds = %6 + br label %16, !dbg !38 + +12: ; preds = %6 + %13 = load ptr, ptr %2, align 8, !dbg !39 + %14 = getelementptr inbounds %struct.Array, ptr %13, i32 0, i32 0, !dbg !40 + %15 = load ptr, ptr %14, align 8, !dbg !40 + call void @free(ptr noundef %15) #5, !dbg !41 + br label %16, !dbg !42 + +16: ; preds = %12, %11, %5 + ret void, !dbg !42 +} + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: nounwind +declare void @free(ptr noundef) #2 + +; Function Attrs: noinline nounwind uwtable +define dso_local void @cleanup_result(ptr noundef %0) #0 !dbg !43 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8 + call void @llvm.dbg.declare(metadata ptr %2, metadata !46, metadata !DIExpression()), !dbg !47 + %3 = load ptr, ptr %2, align 8, !dbg !48 + %4 = icmp ne ptr %3, null, !dbg !48 + br i1 %4, label %6, label %5, !dbg !50 + +5: ; preds = %1 + br label %19, !dbg !51 + +6: ; preds = %1 + %7 = load ptr, ptr %2, align 8, !dbg !52 + %8 = getelementptr inbounds %struct.Result, ptr %7, i32 0, i32 0, !dbg !54 + %9 = load ptr, ptr %8, align 8, !dbg !54 + %10 = icmp ne ptr %9, null, !dbg !52 + br i1 %10, label %12, label %11, !dbg !55 + +11: ; preds = %6 + br label %19, !dbg !56 + +12: ; preds = %6 + %13 = load ptr, ptr %2, align 8, !dbg !57 + %14 = getelementptr inbounds %struct.Result, ptr %13, i32 0, i32 0, !dbg !58 + %15 = load ptr, ptr %14, align 8, !dbg !58 + call void @cleanup_array(ptr noundef %15), !dbg !59 + %16 = load ptr, ptr %2, align 8, !dbg !60 + %17 = getelementptr inbounds %struct.Result, ptr %16, i32 0, i32 0, !dbg !61 + %18 = load ptr, ptr %17, align 8, !dbg !61 + call void @free(ptr noundef %18) #5, !dbg !62 + br label %19, !dbg !63 + +19: ; preds = %12, %11, %5 + ret void, !dbg !63 +} + +; Function Attrs: noinline nounwind uwtable +define dso_local i32 @do_work(ptr noundef %0, ptr noundef %1, ptr noundef %2) #0 !dbg !64 { + %4 = alloca i32, align 4 + %5 = alloca ptr, align 8 + %6 = alloca ptr, align 8 + %7 = alloca ptr, align 8 + %8 = alloca i32, align 4 + %9 = alloca ptr, align 8 + %10 = alloca i32, align 4 + %11 = alloca i32, align 4 + store ptr %0, ptr %5, align 8 + call void @llvm.dbg.declare(metadata ptr %5, metadata !67, metadata !DIExpression()), !dbg !68 + store ptr %1, ptr %6, align 8 + call void @llvm.dbg.declare(metadata ptr %6, metadata !69, metadata !DIExpression()), !dbg !70 + store ptr %2, ptr %7, align 8 + call void @llvm.dbg.declare(metadata ptr %7, metadata !71, metadata !DIExpression()), !dbg !72 + %12 = load ptr, ptr %5, align 8, !dbg !73 + %13 = icmp ne ptr %12, null, !dbg !73 + br i1 %13, label %14, label %17, !dbg !75 + +14: ; preds = %3 + %15 = load ptr, ptr %6, align 8, !dbg !76 + %16 = icmp ne ptr %15, null, !dbg !76 + br i1 %16, label %18, label %17, !dbg !77 + +17: ; preds = %14, %3 + store i32 -1, ptr %4, align 4, !dbg !78 + br label %106, !dbg !78 + +18: ; preds = %14 + %19 = load ptr, ptr %5, align 8, !dbg !79 + %20 = getelementptr inbounds %struct.Array, ptr %19, i32 0, i32 1, !dbg !81 + %21 = load i32, ptr %20, align 8, !dbg !81 + %22 = load ptr, ptr %6, align 8, !dbg !82 + %23 = getelementptr inbounds %struct.Array, ptr %22, i32 0, i32 1, !dbg !83 + %24 = load i32, ptr %23, align 8, !dbg !83 + %25 = icmp ne i32 %21, %24, !dbg !84 + br i1 %25, label %26, label %27, !dbg !85 + +26: ; preds = %18 + store i32 -1, ptr %4, align 4, !dbg !86 + br label %106, !dbg !86 + +27: ; preds = %18 + call void @llvm.dbg.declare(metadata ptr %8, metadata !87, metadata !DIExpression()), !dbg !89 + %28 = load ptr, ptr %5, align 8, !dbg !90 + %29 = getelementptr inbounds %struct.Array, ptr %28, i32 0, i32 1, !dbg !91 + %30 = load i32, ptr %29, align 8, !dbg !91 + store i32 %30, ptr %8, align 4, !dbg !89 + call void @llvm.dbg.declare(metadata ptr %9, metadata !92, metadata !DIExpression()), !dbg !93 + %31 = load ptr, ptr %7, align 8, !dbg !94 + %32 = getelementptr inbounds %struct.Result, ptr %31, i32 0, i32 0, !dbg !96 + %33 = load ptr, ptr %32, align 8, !dbg !96 + %34 = icmp eq ptr %33, null, !dbg !97 + br i1 %34, label %35, label %44, !dbg !98 + +35: ; preds = %27 + %36 = call noalias ptr @malloc(i64 noundef 16) #6, !dbg !99 + store ptr %36, ptr %9, align 8, !dbg !101 + %37 = load ptr, ptr %9, align 8, !dbg !102 + %38 = getelementptr inbounds %struct.Array, ptr %37, i32 0, i32 0, !dbg !103 + store ptr null, ptr %38, align 8, !dbg !104 + %39 = load ptr, ptr %9, align 8, !dbg !105 + %40 = getelementptr inbounds %struct.Array, ptr %39, i32 0, i32 1, !dbg !106 + store i32 0, ptr %40, align 8, !dbg !107 + %41 = load ptr, ptr %9, align 8, !dbg !108 + %42 = load ptr, ptr %7, align 8, !dbg !109 + %43 = getelementptr inbounds %struct.Result, ptr %42, i32 0, i32 0, !dbg !110 + store ptr %41, ptr %43, align 8, !dbg !111 + br label %48, !dbg !112 + +44: ; preds = %27 + %45 = load ptr, ptr %7, align 8, !dbg !113 + %46 = getelementptr inbounds %struct.Result, ptr %45, i32 0, i32 0, !dbg !115 + %47 = load ptr, ptr %46, align 8, !dbg !115 + store ptr %47, ptr %9, align 8, !dbg !116 + br label %48 + +48: ; preds = %44, %35 + %49 = load ptr, ptr %9, align 8, !dbg !117 + %50 = getelementptr inbounds %struct.Array, ptr %49, i32 0, i32 0, !dbg !119 + %51 = load ptr, ptr %50, align 8, !dbg !119 + %52 = icmp ne ptr %51, null, !dbg !117 + br i1 %52, label %53, label %57, !dbg !120 + +53: ; preds = %48 + %54 = load ptr, ptr %9, align 8, !dbg !121 + %55 = getelementptr inbounds %struct.Array, ptr %54, i32 0, i32 0, !dbg !122 + %56 = load ptr, ptr %55, align 8, !dbg !122 + call void @free(ptr noundef %56) #5, !dbg !123 + br label %57, !dbg !123 + +57: ; preds = %53, %48 + %58 = load i32, ptr %8, align 4, !dbg !124 + %59 = sext i32 %58 to i64, !dbg !124 + %60 = mul i64 %59, 4, !dbg !125 + %61 = call noalias ptr @malloc(i64 noundef %60) #6, !dbg !126 + %62 = load ptr, ptr %9, align 8, !dbg !127 + %63 = getelementptr inbounds %struct.Array, ptr %62, i32 0, i32 0, !dbg !128 + store ptr %61, ptr %63, align 8, !dbg !129 + %64 = load i32, ptr %8, align 4, !dbg !130 + %65 = load ptr, ptr %9, align 8, !dbg !131 + %66 = getelementptr inbounds %struct.Array, ptr %65, i32 0, i32 1, !dbg !132 + store i32 %64, ptr %66, align 8, !dbg !133 + call void @llvm.dbg.declare(metadata ptr %10, metadata !134, metadata !DIExpression()), !dbg !135 + store i32 0, ptr %10, align 4, !dbg !135 + call void @llvm.dbg.declare(metadata ptr %11, metadata !136, metadata !DIExpression()), !dbg !138 + store i32 0, ptr %11, align 4, !dbg !138 + br label %67, !dbg !139 + +67: ; preds = %102, %57 + %68 = load i32, ptr %11, align 4, !dbg !140 + %69 = load i32, ptr %8, align 4, !dbg !142 + %70 = icmp slt i32 %68, %69, !dbg !143 + br i1 %70, label %71, label %105, !dbg !144 + +71: ; preds = %67 + %72 = load ptr, ptr %5, align 8, !dbg !145 + %73 = getelementptr inbounds %struct.Array, ptr %72, i32 0, i32 0, !dbg !147 + %74 = load ptr, ptr %73, align 8, !dbg !147 + %75 = load i32, ptr %11, align 4, !dbg !148 + %76 = sext i32 %75 to i64, !dbg !145 + %77 = getelementptr inbounds i32, ptr %74, i64 %76, !dbg !145 + %78 = load i32, ptr %77, align 4, !dbg !145 + %79 = load ptr, ptr %6, align 8, !dbg !149 + %80 = getelementptr inbounds %struct.Array, ptr %79, i32 0, i32 0, !dbg !150 + %81 = load ptr, ptr %80, align 8, !dbg !150 + %82 = load i32, ptr %11, align 4, !dbg !151 + %83 = sext i32 %82 to i64, !dbg !149 + %84 = getelementptr inbounds i32, ptr %81, i64 %83, !dbg !149 + %85 = load i32, ptr %84, align 4, !dbg !149 + %86 = mul nsw i32 %78, %85, !dbg !152 + %87 = load ptr, ptr %9, align 8, !dbg !153 + %88 = getelementptr inbounds %struct.Array, ptr %87, i32 0, i32 0, !dbg !154 + %89 = load ptr, ptr %88, align 8, !dbg !154 + %90 = load i32, ptr %11, align 4, !dbg !155 + %91 = sext i32 %90 to i64, !dbg !153 + %92 = getelementptr inbounds i32, ptr %89, i64 %91, !dbg !153 + store i32 %86, ptr %92, align 4, !dbg !156 + %93 = load ptr, ptr %9, align 8, !dbg !157 + %94 = getelementptr inbounds %struct.Array, ptr %93, i32 0, i32 0, !dbg !158 + %95 = load ptr, ptr %94, align 8, !dbg !158 + %96 = load i32, ptr %11, align 4, !dbg !159 + %97 = sext i32 %96 to i64, !dbg !157 + %98 = getelementptr inbounds i32, ptr %95, i64 %97, !dbg !157 + %99 = load i32, ptr %98, align 4, !dbg !157 + %100 = load i32, ptr %10, align 4, !dbg !160 + %101 = add nsw i32 %100, %99, !dbg !160 + store i32 %101, ptr %10, align 4, !dbg !160 + br label %102, !dbg !161 + +102: ; preds = %71 + %103 = load i32, ptr %11, align 4, !dbg !162 + %104 = add nsw i32 %103, 1, !dbg !162 + store i32 %104, ptr %11, align 4, !dbg !162 + br label %67, !dbg !163, !llvm.loop !164 + +105: ; preds = %67 + store i32 0, ptr %4, align 4, !dbg !167 + br label %106, !dbg !167 + +106: ; preds = %105, %26, %17 + %107 = load i32, ptr %4, align 4, !dbg !168 + ret i32 %107, !dbg !168 +} + +; Function Attrs: nounwind allocsize(0) +declare noalias ptr @malloc(i64 noundef) #3 + +; Function Attrs: noinline nounwind uwtable +define dso_local ptr @gen_array(i32 noundef %0) #0 !dbg !169 { + %2 = alloca ptr, align 8 + %3 = alloca i32, align 4 + %4 = alloca ptr, align 8 + %5 = alloca i32, align 4 + store i32 %0, ptr %3, align 4 + call void @llvm.dbg.declare(metadata ptr %3, metadata !172, metadata !DIExpression()), !dbg !173 + %6 = load i32, ptr %3, align 4, !dbg !174 + %7 = icmp slt i32 %6, 0, !dbg !176 + br i1 %7, label %8, label %9, !dbg !177 + +8: ; preds = %1 + store ptr null, ptr %2, align 8, !dbg !178 + br label %37, !dbg !178 + +9: ; preds = %1 + call void @llvm.dbg.declare(metadata ptr %4, metadata !179, metadata !DIExpression()), !dbg !180 + %10 = call noalias ptr @malloc(i64 noundef 16) #6, !dbg !181 + store ptr %10, ptr %4, align 8, !dbg !180 + %11 = load i32, ptr %3, align 4, !dbg !182 + %12 = load ptr, ptr %4, align 8, !dbg !183 + %13 = getelementptr inbounds %struct.Array, ptr %12, i32 0, i32 1, !dbg !184 + store i32 %11, ptr %13, align 8, !dbg !185 + %14 = load i32, ptr %3, align 4, !dbg !186 + %15 = sext i32 %14 to i64, !dbg !186 + %16 = mul i64 %15, 4, !dbg !187 + %17 = call noalias ptr @malloc(i64 noundef %16) #6, !dbg !188 + %18 = load ptr, ptr %4, align 8, !dbg !189 + %19 = getelementptr inbounds %struct.Array, ptr %18, i32 0, i32 0, !dbg !190 + store ptr %17, ptr %19, align 8, !dbg !191 + call void @llvm.dbg.declare(metadata ptr %5, metadata !192, metadata !DIExpression()), !dbg !194 + store i32 0, ptr %5, align 4, !dbg !194 + br label %20, !dbg !195 + +20: ; preds = %32, %9 + %21 = load i32, ptr %5, align 4, !dbg !196 + %22 = load i32, ptr %3, align 4, !dbg !198 + %23 = icmp slt i32 %21, %22, !dbg !199 + br i1 %23, label %24, label %35, !dbg !200 + +24: ; preds = %20 + %25 = call i32 @rand() #5, !dbg !201 + %26 = load ptr, ptr %4, align 8, !dbg !203 + %27 = getelementptr inbounds %struct.Array, ptr %26, i32 0, i32 0, !dbg !204 + %28 = load ptr, ptr %27, align 8, !dbg !204 + %29 = load i32, ptr %5, align 4, !dbg !205 + %30 = sext i32 %29 to i64, !dbg !203 + %31 = getelementptr inbounds i32, ptr %28, i64 %30, !dbg !203 + store i32 %25, ptr %31, align 4, !dbg !206 + br label %32, !dbg !207 + +32: ; preds = %24 + %33 = load i32, ptr %5, align 4, !dbg !208 + %34 = add nsw i32 %33, 1, !dbg !208 + store i32 %34, ptr %5, align 4, !dbg !208 + br label %20, !dbg !209, !llvm.loop !210 + +35: ; preds = %20 + %36 = load ptr, ptr %4, align 8, !dbg !212 + store ptr %36, ptr %2, align 8, !dbg !213 + br label %37, !dbg !213 + +37: ; preds = %35, %8 + %38 = load ptr, ptr %2, align 8, !dbg !214 + ret ptr %38, !dbg !214 +} + +; Function Attrs: nounwind +declare i32 @rand() #2 + +; Function Attrs: noinline nounwind uwtable +define dso_local i32 @caller() #0 !dbg !215 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca ptr, align 8 + %4 = alloca ptr, align 8 + %5 = alloca ptr, align 8 + %6 = alloca i32, align 4 + %7 = alloca i32, align 4 + call void @llvm.dbg.declare(metadata ptr %2, metadata !218, metadata !DIExpression()), !dbg !219 + store i32 100, ptr %2, align 4, !dbg !219 + call void @llvm.dbg.declare(metadata ptr %3, metadata !220, metadata !DIExpression()), !dbg !221 + %8 = call ptr @gen_array(i32 noundef 100), !dbg !222 + store ptr %8, ptr %3, align 8, !dbg !221 + call void @llvm.dbg.declare(metadata ptr %4, metadata !223, metadata !DIExpression()), !dbg !224 + %9 = call ptr @gen_array(i32 noundef 100), !dbg !225 + store ptr %9, ptr %4, align 8, !dbg !224 + call void @llvm.dbg.declare(metadata ptr %5, metadata !226, metadata !DIExpression()), !dbg !227 + %10 = call noalias ptr @malloc(i64 noundef 16) #6, !dbg !228 + store ptr %10, ptr %5, align 8, !dbg !227 + call void @llvm.dbg.declare(metadata ptr %6, metadata !229, metadata !DIExpression()), !dbg !230 + store i32 -1, ptr %6, align 4, !dbg !230 + call void @llvm.dbg.declare(metadata ptr %7, metadata !231, metadata !DIExpression()), !dbg !232 + %11 = load ptr, ptr %3, align 8, !dbg !233 + %12 = load ptr, ptr %4, align 8, !dbg !234 + %13 = load ptr, ptr %5, align 8, !dbg !235 + %14 = call i32 @do_work(ptr noundef %11, ptr noundef %12, ptr noundef %13), !dbg !236 + store i32 %14, ptr %7, align 4, !dbg !232 + %15 = load i32, ptr %7, align 4, !dbg !237 + %16 = icmp eq i32 %15, -1, !dbg !239 + br i1 %16, label %17, label %18, !dbg !240 + +17: ; preds = %0 + br label %30, !dbg !241 + +18: ; preds = %0 + %19 = load ptr, ptr %5, align 8, !dbg !243 + %20 = getelementptr inbounds %struct.Result, ptr %19, i32 0, i32 1, !dbg !244 + %21 = load i32, ptr %20, align 8, !dbg !244 + store i32 %21, ptr %6, align 4, !dbg !245 + %22 = load i32, ptr %6, align 4, !dbg !246 + %23 = icmp eq i32 %22, -1, !dbg !248 + br i1 %23, label %24, label %26, !dbg !249 + +24: ; preds = %18 + %25 = call i32 @caller(), !dbg !250 + store i32 %25, ptr %1, align 4, !dbg !251 + br label %35, !dbg !251 + +26: ; preds = %18 + %27 = load ptr, ptr %5, align 8, !dbg !252 + %28 = getelementptr inbounds %struct.Result, ptr %27, i32 0, i32 0, !dbg !253 + %29 = load ptr, ptr %28, align 8, !dbg !253 + call void @use_dot_vector(ptr noundef %29), !dbg !254 + br label %30, !dbg !254 + +30: ; preds = %26, %17 + call void @llvm.dbg.label(metadata !255), !dbg !256 + %31 = load ptr, ptr %3, align 8, !dbg !257 + call void @cleanup_array(ptr noundef %31), !dbg !258 + %32 = load ptr, ptr %4, align 8, !dbg !259 + call void @cleanup_array(ptr noundef %32), !dbg !260 + %33 = load ptr, ptr %5, align 8, !dbg !261 + call void @cleanup_result(ptr noundef %33), !dbg !262 + %34 = load i32, ptr %6, align 4, !dbg !263 + store i32 %34, ptr %1, align 4, !dbg !264 + br label %35, !dbg !264 + +35: ; preds = %30, %24 + %36 = load i32, ptr %1, align 4, !dbg !265 + ret i32 %36, !dbg !265 +} + +declare void @use_dot_vector(ptr noundef) #4 + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.label(metadata) #1 + +attributes #0 = { noinline nounwind uwtable "frame-pointer"="all" } +attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +attributes #2 = { nounwind "frame-pointer"="all" } +attributes #3 = { nounwind allocsize(0) "frame-pointer"="all" } +attributes #4 = { "frame-pointer"="all" } +attributes #5 = { nounwind } +attributes #6 = { nounwind allocsize(0) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!16, !17, !18, !19, !20, !21, !22} +!llvm.ident = !{!23} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Fuchsia clang version 16.0.0 (https://llvm.googlesource.com/llvm-project f85c1f3b7c0bda64aef12201e2f5bbad6028582d)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "dot.c", directory: "/usr/local/google/home/paulkirth/test/stack-frame-dump", checksumkind: CSK_MD5, checksum: "bd8ba1fe67914c5427978672a19a51d2") +!2 = !{!3, !4, !8, !11} +!3 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64) +!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Array", file: !1, line: 3, size: 128, elements: !6) +!6 = !{!7, !10} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !5, file: !1, line: 4, baseType: !8, size: 64) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "size", scope: !5, file: !1, line: 5, baseType: !9, size: 32, offset: 64) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Result", file: !1, line: 8, size: 128, elements: !13) +!13 = !{!14, !15} +!14 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !12, file: !1, line: 9, baseType: !4, size: 64) +!15 = !DIDerivedType(tag: DW_TAG_member, name: "sum", scope: !12, file: !1, line: 10, baseType: !9, size: 32, offset: 64) +!16 = !{i32 7, !"Dwarf Version", i32 5} +!17 = !{i32 2, !"Debug Info Version", i32 3} +!18 = !{i32 1, !"wchar_size", i32 4} +!19 = !{i32 8, !"PIC Level", i32 2} +!20 = !{i32 7, !"PIE Level", i32 2} +!21 = !{i32 7, !"uwtable", i32 2} +!22 = !{i32 7, !"frame-pointer", i32 2} +!23 = !{!"Fuchsia clang version 16.0.0 (https://llvm.googlesource.com/llvm-project f85c1f3b7c0bda64aef12201e2f5bbad6028582d)"} +!24 = distinct !DISubprogram(name: "cleanup_array", scope: !1, file: !1, line: 13, type: !25, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27) +!25 = !DISubroutineType(types: !26) +!26 = !{null, !4} +!27 = !{} +!28 = !DILocalVariable(name: "a", arg: 1, scope: !24, file: !1, line: 13, type: !4) +!29 = !DILocation(line: 13, column: 34, scope: !24) +!30 = !DILocation(line: 14, column: 8, scope: !31) +!31 = distinct !DILexicalBlock(scope: !24, file: !1, line: 14, column: 7) +!32 = !DILocation(line: 14, column: 7, scope: !24) +!33 = !DILocation(line: 15, column: 5, scope: !31) +!34 = !DILocation(line: 16, column: 8, scope: !35) +!35 = distinct !DILexicalBlock(scope: !24, file: !1, line: 16, column: 7) +!36 = !DILocation(line: 16, column: 11, scope: !35) +!37 = !DILocation(line: 16, column: 7, scope: !24) +!38 = !DILocation(line: 17, column: 5, scope: !35) +!39 = !DILocation(line: 18, column: 8, scope: !24) +!40 = !DILocation(line: 18, column: 11, scope: !24) +!41 = !DILocation(line: 18, column: 3, scope: !24) +!42 = !DILocation(line: 19, column: 1, scope: !24) +!43 = distinct !DISubprogram(name: "cleanup_result", scope: !1, file: !1, line: 21, type: !44, scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27) +!44 = !DISubroutineType(types: !45) +!45 = !{null, !11} +!46 = !DILocalVariable(name: "res", arg: 1, scope: !43, file: !1, line: 21, type: !11) +!47 = !DILocation(line: 21, column: 36, scope: !43) +!48 = !DILocation(line: 22, column: 8, scope: !49) +!49 = distinct !DILexicalBlock(scope: !43, file: !1, line: 22, column: 7) +!50 = !DILocation(line: 22, column: 7, scope: !43) +!51 = !DILocation(line: 23, column: 5, scope: !49) +!52 = !DILocation(line: 24, column: 8, scope: !53) +!53 = distinct !DILexicalBlock(scope: !43, file: !1, line: 24, column: 7) +!54 = !DILocation(line: 24, column: 13, scope: !53) +!55 = !DILocation(line: 24, column: 7, scope: !43) +!56 = !DILocation(line: 25, column: 5, scope: !53) +!57 = !DILocation(line: 26, column: 17, scope: !43) +!58 = !DILocation(line: 26, column: 22, scope: !43) +!59 = !DILocation(line: 26, column: 3, scope: !43) +!60 = !DILocation(line: 27, column: 8, scope: !43) +!61 = !DILocation(line: 27, column: 13, scope: !43) +!62 = !DILocation(line: 27, column: 3, scope: !43) +!63 = !DILocation(line: 28, column: 1, scope: !43) +!64 = distinct !DISubprogram(name: "do_work", scope: !1, file: !1, line: 32, type: !65, scopeLine: 32, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27) +!65 = !DISubroutineType(types: !66) +!66 = !{!9, !4, !4, !11} +!67 = !DILocalVariable(name: "A", arg: 1, scope: !64, file: !1, line: 32, type: !4) +!68 = !DILocation(line: 32, column: 27, scope: !64) +!69 = !DILocalVariable(name: "B", arg: 2, scope: !64, file: !1, line: 32, type: !4) +!70 = !DILocation(line: 32, column: 44, scope: !64) +!71 = !DILocalVariable(name: "out", arg: 3, scope: !64, file: !1, line: 32, type: !11) +!72 = !DILocation(line: 32, column: 62, scope: !64) +!73 = !DILocation(line: 33, column: 8, scope: !74) +!74 = distinct !DILexicalBlock(scope: !64, file: !1, line: 33, column: 7) +!75 = !DILocation(line: 33, column: 10, scope: !74) +!76 = !DILocation(line: 33, column: 14, scope: !74) +!77 = !DILocation(line: 33, column: 7, scope: !64) +!78 = !DILocation(line: 34, column: 5, scope: !74) +!79 = !DILocation(line: 35, column: 7, scope: !80) +!80 = distinct !DILexicalBlock(scope: !64, file: !1, line: 35, column: 7) +!81 = !DILocation(line: 35, column: 10, scope: !80) +!82 = !DILocation(line: 35, column: 18, scope: !80) +!83 = !DILocation(line: 35, column: 21, scope: !80) +!84 = !DILocation(line: 35, column: 15, scope: !80) +!85 = !DILocation(line: 35, column: 7, scope: !64) +!86 = !DILocation(line: 36, column: 5, scope: !80) +!87 = !DILocalVariable(name: "len", scope: !64, file: !1, line: 37, type: !88) +!88 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !9) +!89 = !DILocation(line: 37, column: 13, scope: !64) +!90 = !DILocation(line: 37, column: 19, scope: !64) +!91 = !DILocation(line: 37, column: 22, scope: !64) +!92 = !DILocalVariable(name: "AB", scope: !64, file: !1, line: 38, type: !4) +!93 = !DILocation(line: 38, column: 17, scope: !64) +!94 = !DILocation(line: 39, column: 7, scope: !95) +!95 = distinct !DILexicalBlock(scope: !64, file: !1, line: 39, column: 7) +!96 = !DILocation(line: 39, column: 12, scope: !95) +!97 = !DILocation(line: 39, column: 17, scope: !95) +!98 = !DILocation(line: 39, column: 7, scope: !64) +!99 = !DILocation(line: 40, column: 26, scope: !100) +!100 = distinct !DILexicalBlock(scope: !95, file: !1, line: 39, column: 26) +!101 = !DILocation(line: 40, column: 8, scope: !100) +!102 = !DILocation(line: 41, column: 5, scope: !100) +!103 = !DILocation(line: 41, column: 9, scope: !100) +!104 = !DILocation(line: 41, column: 14, scope: !100) +!105 = !DILocation(line: 42, column: 5, scope: !100) +!106 = !DILocation(line: 42, column: 9, scope: !100) +!107 = !DILocation(line: 42, column: 14, scope: !100) +!108 = !DILocation(line: 43, column: 17, scope: !100) +!109 = !DILocation(line: 43, column: 5, scope: !100) +!110 = !DILocation(line: 43, column: 10, scope: !100) +!111 = !DILocation(line: 43, column: 15, scope: !100) +!112 = !DILocation(line: 44, column: 3, scope: !100) +!113 = !DILocation(line: 45, column: 10, scope: !114) +!114 = distinct !DILexicalBlock(scope: !95, file: !1, line: 44, column: 10) +!115 = !DILocation(line: 45, column: 15, scope: !114) +!116 = !DILocation(line: 45, column: 8, scope: !114) +!117 = !DILocation(line: 48, column: 7, scope: !118) +!118 = distinct !DILexicalBlock(scope: !64, file: !1, line: 48, column: 7) +!119 = !DILocation(line: 48, column: 11, scope: !118) +!120 = !DILocation(line: 48, column: 7, scope: !64) +!121 = !DILocation(line: 49, column: 10, scope: !118) +!122 = !DILocation(line: 49, column: 14, scope: !118) +!123 = !DILocation(line: 49, column: 5, scope: !118) +!124 = !DILocation(line: 51, column: 28, scope: !64) +!125 = !DILocation(line: 51, column: 32, scope: !64) +!126 = !DILocation(line: 51, column: 21, scope: !64) +!127 = !DILocation(line: 51, column: 3, scope: !64) +!128 = !DILocation(line: 51, column: 7, scope: !64) +!129 = !DILocation(line: 51, column: 12, scope: !64) +!130 = !DILocation(line: 52, column: 14, scope: !64) +!131 = !DILocation(line: 52, column: 3, scope: !64) +!132 = !DILocation(line: 52, column: 7, scope: !64) +!133 = !DILocation(line: 52, column: 12, scope: !64) +!134 = !DILocalVariable(name: "sum", scope: !64, file: !1, line: 54, type: !9) +!135 = !DILocation(line: 54, column: 7, scope: !64) +!136 = !DILocalVariable(name: "i", scope: !137, file: !1, line: 55, type: !9) +!137 = distinct !DILexicalBlock(scope: !64, file: !1, line: 55, column: 3) +!138 = !DILocation(line: 55, column: 12, scope: !137) +!139 = !DILocation(line: 55, column: 8, scope: !137) +!140 = !DILocation(line: 55, column: 19, scope: !141) +!141 = distinct !DILexicalBlock(scope: !137, file: !1, line: 55, column: 3) +!142 = !DILocation(line: 55, column: 23, scope: !141) +!143 = !DILocation(line: 55, column: 21, scope: !141) +!144 = !DILocation(line: 55, column: 3, scope: !137) +!145 = !DILocation(line: 56, column: 19, scope: !146) +!146 = distinct !DILexicalBlock(scope: !141, file: !1, line: 55, column: 33) +!147 = !DILocation(line: 56, column: 22, scope: !146) +!148 = !DILocation(line: 56, column: 27, scope: !146) +!149 = !DILocation(line: 56, column: 32, scope: !146) +!150 = !DILocation(line: 56, column: 35, scope: !146) +!151 = !DILocation(line: 56, column: 40, scope: !146) +!152 = !DILocation(line: 56, column: 30, scope: !146) +!153 = !DILocation(line: 56, column: 5, scope: !146) +!154 = !DILocation(line: 56, column: 9, scope: !146) +!155 = !DILocation(line: 56, column: 14, scope: !146) +!156 = !DILocation(line: 56, column: 17, scope: !146) +!157 = !DILocation(line: 57, column: 12, scope: !146) +!158 = !DILocation(line: 57, column: 16, scope: !146) +!159 = !DILocation(line: 57, column: 21, scope: !146) +!160 = !DILocation(line: 57, column: 9, scope: !146) +!161 = !DILocation(line: 58, column: 3, scope: !146) +!162 = !DILocation(line: 55, column: 28, scope: !141) +!163 = !DILocation(line: 55, column: 3, scope: !141) +!164 = distinct !{!164, !144, !165, !166} +!165 = !DILocation(line: 58, column: 3, scope: !137) +!166 = !{!"llvm.loop.mustprogress"} +!167 = !DILocation(line: 59, column: 3, scope: !64) +!168 = !DILocation(line: 60, column: 1, scope: !64) +!169 = distinct !DISubprogram(name: "gen_array", scope: !1, file: !1, line: 62, type: !170, scopeLine: 62, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27) +!170 = !DISubroutineType(types: !171) +!171 = !{!4, !9} +!172 = !DILocalVariable(name: "size", arg: 1, scope: !169, file: !1, line: 62, type: !9) +!173 = !DILocation(line: 62, column: 29, scope: !169) +!174 = !DILocation(line: 63, column: 7, scope: !175) +!175 = distinct !DILexicalBlock(scope: !169, file: !1, line: 63, column: 7) +!176 = !DILocation(line: 63, column: 12, scope: !175) +!177 = !DILocation(line: 63, column: 7, scope: !169) +!178 = !DILocation(line: 64, column: 5, scope: !175) +!179 = !DILocalVariable(name: "res", scope: !169, file: !1, line: 65, type: !4) +!180 = !DILocation(line: 65, column: 17, scope: !169) +!181 = !DILocation(line: 65, column: 39, scope: !169) +!182 = !DILocation(line: 66, column: 15, scope: !169) +!183 = !DILocation(line: 66, column: 3, scope: !169) +!184 = !DILocation(line: 66, column: 8, scope: !169) +!185 = !DILocation(line: 66, column: 13, scope: !169) +!186 = !DILocation(line: 67, column: 29, scope: !169) +!187 = !DILocation(line: 67, column: 34, scope: !169) +!188 = !DILocation(line: 67, column: 22, scope: !169) +!189 = !DILocation(line: 67, column: 3, scope: !169) +!190 = !DILocation(line: 67, column: 8, scope: !169) +!191 = !DILocation(line: 67, column: 13, scope: !169) +!192 = !DILocalVariable(name: "i", scope: !193, file: !1, line: 69, type: !9) +!193 = distinct !DILexicalBlock(scope: !169, file: !1, line: 69, column: 3) +!194 = !DILocation(line: 69, column: 12, scope: !193) +!195 = !DILocation(line: 69, column: 8, scope: !193) +!196 = !DILocation(line: 69, column: 19, scope: !197) +!197 = distinct !DILexicalBlock(scope: !193, file: !1, line: 69, column: 3) +!198 = !DILocation(line: 69, column: 23, scope: !197) +!199 = !DILocation(line: 69, column: 21, scope: !197) +!200 = !DILocation(line: 69, column: 3, scope: !193) +!201 = !DILocation(line: 70, column: 20, scope: !202) +!202 = distinct !DILexicalBlock(scope: !197, file: !1, line: 69, column: 34) +!203 = !DILocation(line: 70, column: 5, scope: !202) +!204 = !DILocation(line: 70, column: 10, scope: !202) +!205 = !DILocation(line: 70, column: 15, scope: !202) +!206 = !DILocation(line: 70, column: 18, scope: !202) +!207 = !DILocation(line: 71, column: 3, scope: !202) +!208 = !DILocation(line: 69, column: 29, scope: !197) +!209 = !DILocation(line: 69, column: 3, scope: !197) +!210 = distinct !{!210, !200, !211, !166} +!211 = !DILocation(line: 71, column: 3, scope: !193) +!212 = !DILocation(line: 73, column: 10, scope: !169) +!213 = !DILocation(line: 73, column: 3, scope: !169) +!214 = !DILocation(line: 74, column: 1, scope: !169) +!215 = distinct !DISubprogram(name: "caller", scope: !1, file: !1, line: 76, type: !216, scopeLine: 76, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !27) +!216 = !DISubroutineType(types: !217) +!217 = !{!9} +!218 = !DILocalVariable(name: "size", scope: !215, file: !1, line: 77, type: !88) +!219 = !DILocation(line: 77, column: 13, scope: !215) +!220 = !DILocalVariable(name: "A", scope: !215, file: !1, line: 78, type: !4) +!221 = !DILocation(line: 78, column: 17, scope: !215) +!222 = !DILocation(line: 78, column: 21, scope: !215) +!223 = !DILocalVariable(name: "B", scope: !215, file: !1, line: 79, type: !4) +!224 = !DILocation(line: 79, column: 17, scope: !215) +!225 = !DILocation(line: 79, column: 21, scope: !215) +!226 = !DILocalVariable(name: "res", scope: !215, file: !1, line: 80, type: !11) +!227 = !DILocation(line: 80, column: 18, scope: !215) +!228 = !DILocation(line: 80, column: 41, scope: !215) +!229 = !DILocalVariable(name: "ret", scope: !215, file: !1, line: 81, type: !9) +!230 = !DILocation(line: 81, column: 7, scope: !215) +!231 = !DILocalVariable(name: "err", scope: !215, file: !1, line: 83, type: !9) +!232 = !DILocation(line: 83, column: 7, scope: !215) +!233 = !DILocation(line: 83, column: 21, scope: !215) +!234 = !DILocation(line: 83, column: 24, scope: !215) +!235 = !DILocation(line: 83, column: 27, scope: !215) +!236 = !DILocation(line: 83, column: 13, scope: !215) +!237 = !DILocation(line: 84, column: 7, scope: !238) +!238 = distinct !DILexicalBlock(scope: !215, file: !1, line: 84, column: 7) +!239 = !DILocation(line: 84, column: 11, scope: !238) +!240 = !DILocation(line: 84, column: 7, scope: !215) +!241 = !DILocation(line: 85, column: 5, scope: !242) +!242 = distinct !DILexicalBlock(scope: !238, file: !1, line: 84, column: 18) +!243 = !DILocation(line: 88, column: 9, scope: !215) +!244 = !DILocation(line: 88, column: 14, scope: !215) +!245 = !DILocation(line: 88, column: 7, scope: !215) +!246 = !DILocation(line: 89, column: 7, scope: !247) +!247 = distinct !DILexicalBlock(scope: !215, file: !1, line: 89, column: 7) +!248 = !DILocation(line: 89, column: 11, scope: !247) +!249 = !DILocation(line: 89, column: 7, scope: !215) +!250 = !DILocation(line: 90, column: 12, scope: !247) +!251 = !DILocation(line: 90, column: 5, scope: !247) +!252 = !DILocation(line: 92, column: 18, scope: !215) +!253 = !DILocation(line: 92, column: 23, scope: !215) +!254 = !DILocation(line: 92, column: 3, scope: !215) +!255 = !DILabel(scope: !215, name: "cleanup", file: !1, line: 94) +!256 = !DILocation(line: 94, column: 1, scope: !215) +!257 = !DILocation(line: 95, column: 17, scope: !215) +!258 = !DILocation(line: 95, column: 3, scope: !215) +!259 = !DILocation(line: 96, column: 17, scope: !215) +!260 = !DILocation(line: 96, column: 3, scope: !215) +!261 = !DILocation(line: 97, column: 18, scope: !215) +!262 = !DILocation(line: 97, column: 3, scope: !215) +!263 = !DILocation(line: 99, column: 10, scope: !215) +!264 = !DILocation(line: 99, column: 3, scope: !215) +!265 = !DILocation(line: 100, column: 1, scope: !215)