From: Adrian Prantl Date: Tue, 7 Nov 2017 00:45:34 +0000 (+0000) Subject: Make DIExpression::createFragmentExpression() return an Optional. X-Git-Tag: llvmorg-6.0.0-rc1~4021 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=25a09dd40853d6fb1137d7847f3cca1a1e813caf;p=platform%2Fupstream%2Fllvm.git Make DIExpression::createFragmentExpression() return an Optional. We can't safely split arithmetic into multiple fragments because we can't express carry-over between fragments. llvm-svn: 317534 --- diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index b1f08e7..c515f6d 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2306,9 +2306,11 @@ public: /// /// \param OffsetInBits Offset of the piece in bits. /// \param SizeInBits Size of the piece in bits. - static DIExpression *createFragmentExpression(const DIExpression *Exp, - unsigned OffsetInBits, - unsigned SizeInBits); + /// \return Creating a fragment expression may fail if \c Expr + /// contains arithmetic operations that would be truncated. + static Optional + createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, + unsigned SizeInBits); }; /// Global variables. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index b42edf8..0d85bcc 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -849,13 +849,14 @@ static void transferDbgValues(SelectionDAG &DAG, SDValue From, SDValue To, break; DIVariable *Var = Dbg->getVariable(); - auto *Fragment = DIExpression::createFragmentExpression( - Dbg->getExpression(), OffsetInBits, To.getValueSizeInBits()); - SDDbgValue *Clone = - DAG.getDbgValue(Var, Fragment, ToNode, To.getResNo(), Dbg->isIndirect(), - Dbg->getDebugLoc(), Dbg->getOrder()); + if (auto Fragment = DIExpression::createFragmentExpression( + Dbg->getExpression(), OffsetInBits, To.getValueSizeInBits())) { + SDDbgValue *Clone = DAG.getDbgValue(Var, *Fragment, ToNode, To.getResNo(), + Dbg->isIndirect(), Dbg->getDebugLoc(), + Dbg->getOrder()); + ClonedDVs.push_back(Clone); + } Dbg->setIsInvalidated(); - ClonedDVs.push_back(Clone); } for (SDDbgValue *Dbg : ClonedDVs) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index f45e264..5579449 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4873,11 +4873,13 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue( for (unsigned E = I + RegCount; I != E; ++I) { // The vregs are guaranteed to be allocated in sequence. Op = MachineOperand::CreateReg(VMI->second + I, false); - auto *FragmentExpr = DIExpression::createFragmentExpression( + auto FragmentExpr = DIExpression::createFragmentExpression( Expr, Offset, RegisterSize); + if (!FragmentExpr) + continue; FuncInfo.ArgDbgValues.push_back( BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), IsDbgDeclare, - Op->getReg(), Variable, FragmentExpr)); + Op->getReg(), Variable, *FragmentExpr)); Offset += RegisterSize; } } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 0a9c5c1..ae02392 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -753,14 +753,23 @@ DIExpression *DIExpression::prepend(const DIExpression *Expr, bool Deref, return DIExpression::get(Expr->getContext(), Ops); } -DIExpression *DIExpression::createFragmentExpression(const DIExpression *Expr, - unsigned OffsetInBits, - unsigned SizeInBits) { +Optional DIExpression::createFragmentExpression( + const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) { SmallVector Ops; // Copy over the expression, but leave off any trailing DW_OP_LLVM_fragment. if (Expr) { for (auto Op : Expr->expr_ops()) { - if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) { + switch (Op.getOp()) { + default: break; + case dwarf::DW_OP_plus: + case dwarf::DW_OP_minus: + // We can't safely split arithmetic into multiple fragments because we + // can't express carry-over between fragments. + // + // FIXME: We *could* preserve the lowest fragment of a constant offset + // operation if the offset fits into SizeInBits. + return None; + case dwarf::DW_OP_LLVM_fragment: { // Make the new offset point into the existing fragment. uint64_t FragmentOffsetInBits = Op.getArg(0); // Op.getArg(0) is FragmentOffsetInBits. @@ -768,7 +777,8 @@ DIExpression *DIExpression::createFragmentExpression(const DIExpression *Expr, assert((OffsetInBits + SizeInBits <= Op.getArg(0) + Op.getArg(1)) && "new fragment outside of original fragment"); OffsetInBits += FragmentOffsetInBits; - break; + continue; + } } Ops.push_back(Op.getOp()); for (unsigned I = 0; I < Op.getNumArgs(); ++I) diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 12090bf..4bb2984 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -448,9 +448,13 @@ static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV, for (auto *GVE : GVs) { DIVariable *Var = GVE->getVariable(); DIExpression *Expr = GVE->getExpression(); - if (NumElements > 1) - Expr = DIExpression::createFragmentExpression(Expr, FragmentOffsetInBits, - FragmentSizeInBits); + if (NumElements > 1) { + if (auto E = DIExpression::createFragmentExpression( + Expr, FragmentOffsetInBits, FragmentSizeInBits)) + Expr = *E; + else + return; + } auto *NGVE = DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr); NGV->addDebugInfo(NGVE); } diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index b968cb8..6de6c8c 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -4133,8 +4133,10 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) { "new fragment is outside of original fragment"); Start -= OrigFragment->OffsetInBits; } - FragmentExpr = - DIExpression::createFragmentExpression(Expr, Start, Size); + if (auto E = DIExpression::createFragmentExpression(Expr, Start, Size)) + FragmentExpr = *E; + else + continue; } // Remove any existing intrinsics describing the same alloca. diff --git a/llvm/test/DebugInfo/ARM/illegal-fragment.ll b/llvm/test/DebugInfo/ARM/illegal-fragment.ll new file mode 100644 index 0000000..41e28fa --- /dev/null +++ b/llvm/test/DebugInfo/ARM/illegal-fragment.ll @@ -0,0 +1,95 @@ +; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s +; CHECK: file format Mach-O arm +; ModuleID = 'test.ll' +source_filename = "test.i" +target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +target triple = "thumbv7s-apple-ios5.0.0" + +%struct.vm_object = type { i64 } + +; Function Attrs: nounwind ssp +define void @f(%struct.vm_object* %object, i64* nocapture readonly %start) local_unnamed_addr #0 !dbg !11 { +entry: + tail call void @llvm.dbg.value(metadata %struct.vm_object* %object, metadata !21, metadata !DIExpression()), !dbg !27 + tail call void @llvm.dbg.value(metadata i64* %start, metadata !22, metadata !DIExpression()), !dbg !28 + tail call void @llvm.dbg.value(metadata i64 %0, metadata !25, metadata !DIExpression()), !dbg !29 + tail call void @llvm.dbg.value(metadata i64 %0, metadata !26, metadata !DIExpression(DW_OP_constu, 4096, DW_OP_minus, DW_OP_stack_value)), !dbg !30 + ; This debug value cannot safely be split into two 32-bit pieces. + ; CHECK-NOT: DW_AT_name(offset) + tail call void @llvm.dbg.value(metadata i32 undef, metadata !23, metadata !DIExpression()), !dbg !31 + br i1 undef, label %for.end, label %for.body.lr.ph, !dbg !31 + +for.body.lr.ph: ; preds = %entry + %0 = load i64, i64* %start, align 4, !dbg !33 + br label %for.body, !dbg !31 + +for.body: ; preds = %for.body, %for.body.lr.ph + %offset.010.in = phi i64 [ %0, %for.body.lr.ph ], [ %offset.010, %for.body ] + %head_size.09 = phi i32 [ undef, %for.body.lr.ph ], [ %sub2, %for.body ] + %offset.010 = add i64 %offset.010.in, -4096 + tail call void @llvm.dbg.value(metadata i32 %head_size.09, metadata !23, metadata !DIExpression()), !dbg !30 + %call = tail call i32 bitcast (i32 (...)* @use to i32 (i64, %struct.vm_object*)*)(i64 %offset.010, %struct.vm_object* %object) #2, !dbg !34 + %sub2 = add i32 %head_size.09, -4096, !dbg !37 + tail call void @llvm.dbg.value(metadata i64 %offset.010, metadata !26, metadata !DIExpression(DW_OP_constu, 4096, DW_OP_minus, DW_OP_stack_value)), !dbg !29 + tail call void @llvm.dbg.value(metadata i32 %sub2, metadata !23, metadata !DIExpression()), !dbg !30 + %tobool = icmp eq i32 %sub2, 0, !dbg !31 + br i1 %tobool, label %for.end, label %for.body, !dbg !31, !llvm.loop !38 + +for.end: ; preds = %for.body, %entry + ret void, !dbg !40 +} + +declare i32 @use(...) local_unnamed_addr + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind ssp } +attributes #1 = { nounwind readnone speculatable } +attributes #2 = { nobuiltin nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!5, !6, !7, !8, !9} +!llvm.ident = !{!10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 (trunk 317434) (llvm/trunk 317437)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3) +!1 = !DIFile(filename: "test.i", directory: "/Data/radar/31209283") +!2 = !{} +!3 = !{!4} +!4 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!5 = !{i32 2, !"Dwarf Version", i32 2} +!6 = !{i32 2, !"Debug Info Version", i32 3} +!7 = !{i32 1, !"wchar_size", i32 4} +!8 = !{i32 1, !"min_enum_size", i32 4} +!9 = !{i32 7, !"PIC Level", i32 2} +!10 = !{!"clang version 6.0.0 (trunk 317434) (llvm/trunk 317437)"} +!11 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 6, type: !12, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !20) +!12 = !DISubroutineType(types: !13) +!13 = !{null, !14, !19} +!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "v_t", file: !1, line: 1, baseType: !15) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 32) +!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v", file: !1, line: 2, size: 64, elements: !17) +!17 = !{!18} +!18 = !DIDerivedType(tag: DW_TAG_member, name: "p", scope: !16, file: !1, line: 3, baseType: !4, size: 64) +!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 32) +!20 = !{!21, !22, !23, !25, !26} +!21 = !DILocalVariable(name: "object", arg: 1, scope: !11, file: !1, line: 6, type: !14) +!22 = !DILocalVariable(name: "start", arg: 2, scope: !11, file: !1, line: 6, type: !19) +!23 = !DILocalVariable(name: "head_size", scope: !11, file: !1, line: 7, type: !24) +!24 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!25 = !DILocalVariable(name: "orig_start", scope: !11, file: !1, line: 8, type: !4) +!26 = !DILocalVariable(name: "offset", scope: !11, file: !1, line: 9, type: !4) +!27 = !DILocation(line: 6, column: 20, scope: !11) +!28 = !DILocation(line: 6, column: 48, scope: !11) +!29 = !DILocation(line: 7, column: 12, scope: !11) +!30 = !DILocation(line: 10, column: 16, scope: !11) +!31 = !DILocation(line: 11, column: 5, scope: !32) +!32 = distinct !DILexicalBlock(scope: !11, file: !1, line: 11, column: 5) +!33 = !DILocation(line: 8, column: 22, scope: !11) +!34 = !DILocation(line: 13, column: 7, scope: !35) +!35 = distinct !DILexicalBlock(scope: !36, file: !1, line: 12, column: 75) +!36 = distinct !DILexicalBlock(scope: !32, file: !1, line: 11, column: 5) +!37 = !DILocation(line: 12, column: 61, scope: !36) +!38 = distinct !{!38, !31, !39} +!39 = !DILocation(line: 14, column: 3, scope: !32) +!40 = !DILocation(line: 15, column: 1, scope: !11)