The current supported vocabulary is limited:
- ``DW_OP_deref`` dereferences the top of the expression stack.
-- ``DW_OP_plus, 93`` adds ``93`` to the working expression.
+- ``DW_OP_plus`` pops the last two entries from the expression stack, adds
+ them together and appends the result to the expression stack.
+- ``DW_OP_minus`` pops the last two entries from the expression stack, subtracts
+ the last entry from the second last entry and appends the result to the
+ expression stack.
- ``DW_OP_plus_uconst, 93`` adds ``93`` to the working expression.
- ``DW_OP_LLVM_fragment, 16, 8`` specifies the offset and size (``16`` and ``8``
here, respectively) of the variable fragment from the working expression. Note
.. code-block:: llvm
!0 = !DIExpression(DW_OP_deref)
- !1 = !DIExpression(DW_OP_plus, 3)
!1 = !DIExpression(DW_OP_plus_uconst, 3)
+ !1 = !DIExpression(DW_OP_constu, 3, DW_OP_plus)
!2 = !DIExpression(DW_OP_bit_piece, 3, 7)
- !3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
+ !3 = !DIExpression(DW_OP_deref, DW_OP_constu, 3, DW_OP_plus, DW_OP_LLVM_fragment, 3, 7)
!4 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
!5 = !DIExpression(DW_OP_constu, 42, DW_OP_stack_value)
/// variable, or the location of a single piece of a variable, or (when using
/// DW_OP_stack_value) is the constant variable value.
///
-/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
-/// and have DW_OP_plus consume the topmost elements on the stack.
-///
/// TODO: Co-allocate the expression elements.
/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
/// storage types.
} // anonynous namespace
+static Error error(const Twine &Message) {
+ return make_error<StringError>(
+ Message, make_error_code(BitcodeError::CorruptedBitcode));
+}
+
class MetadataLoader::MetadataLoaderImpl {
BitcodeReaderMetadataList MetadataList;
BitcodeReaderValueList &ValueList;
}
}
+ /// Upgrade the expression from previous versions.
+ Error upgradeDIExpression(uint64_t FromVersion,
+ MutableArrayRef<uint64_t> &Expr,
+ SmallVectorImpl<uint64_t> &Buffer) {
+ auto N = Expr.size();
+ switch (FromVersion) {
+ default:
+ return error("Invalid record");
+ case 0:
+ if (N >= 3 && Expr[N - 3] == dwarf::DW_OP_bit_piece)
+ Expr[N - 3] = dwarf::DW_OP_LLVM_fragment;
+ LLVM_FALLTHROUGH;
+ case 1:
+ // Move DW_OP_deref to the end.
+ if (N && Expr[0] == dwarf::DW_OP_deref) {
+ auto End = Expr.end();
+ if (Expr.size() >= 3 &&
+ *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
+ End = std::prev(End, 3);
+ std::move(std::next(Expr.begin()), End, Expr.begin());
+ *std::prev(End) = dwarf::DW_OP_deref;
+ }
+ NeedDeclareExpressionUpgrade = true;
+ LLVM_FALLTHROUGH;
+ case 2: {
+ // Change DW_OP_plus to DW_OP_plus_uconst.
+ // Change DW_OP_minus to DW_OP_uconst, DW_OP_minus
+ auto SubExpr = ArrayRef<uint64_t>(Expr);
+ while (!SubExpr.empty()) {
+ // Skip past other operators with their operands
+ // for this version of the IR, obtained from
+ // from historic DIExpression::ExprOperand::getSize().
+ size_t HistoricSize;
+ switch (SubExpr.front()) {
+ default:
+ HistoricSize = 1;
+ break;
+ case dwarf::DW_OP_constu:
+ case dwarf::DW_OP_minus:
+ case dwarf::DW_OP_plus:
+ HistoricSize = 2;
+ break;
+ case dwarf::DW_OP_LLVM_fragment:
+ HistoricSize = 3;
+ break;
+ }
+
+ // If the expression is malformed, make sure we don't
+ // copy more elements than we should.
+ HistoricSize = std::min(SubExpr.size(), HistoricSize);
+ ArrayRef<uint64_t> Args = SubExpr.slice(1, HistoricSize-1);
+
+ switch (SubExpr.front()) {
+ case dwarf::DW_OP_plus:
+ Buffer.push_back(dwarf::DW_OP_plus_uconst);
+ Buffer.append(Args.begin(), Args.end());
+ break;
+ case dwarf::DW_OP_minus:
+ Buffer.push_back(dwarf::DW_OP_constu);
+ Buffer.append(Args.begin(), Args.end());
+ Buffer.push_back(dwarf::DW_OP_minus);
+ break;
+ default:
+ Buffer.push_back(*SubExpr.begin());
+ Buffer.append(Args.begin(), Args.end());
+ break;
+ }
+
+ // Continue with remaining elements.
+ SubExpr = SubExpr.slice(HistoricSize);
+ }
+ Expr = MutableArrayRef<uint64_t>(Buffer);
+ LLVM_FALLTHROUGH;
+ }
+ case 3:
+ // Up-to-date!
+ break;
+ }
+
+ return Error::success();
+ }
+
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); }
};
-static Error error(const Twine &Message) {
- return make_error<StringError>(
- Message, make_error_code(BitcodeError::CorruptedBitcode));
-}
-
Expected<bool>
MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
IndexCursor = Stream;
IsDistinct = Record[0] & 1;
uint64_t Version = Record[0] >> 1;
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
- unsigned N = Elts.size();
- // Perform various upgrades.
- switch (Version) {
- case 0:
- if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
- Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
- LLVM_FALLTHROUGH;
- case 1:
- // Move DW_OP_deref to the end.
- if (N && Elts[0] == dwarf::DW_OP_deref) {
- auto End = Elts.end();
- if (Elts.size() >= 3 && *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
- End = std::prev(End, 3);
- std::move(std::next(Elts.begin()), End, Elts.begin());
- *std::prev(End) = dwarf::DW_OP_deref;
- }
- NeedDeclareExpressionUpgrade = true;
- LLVM_FALLTHROUGH;
- case 2:
- // Up-to-date!
- break;
- default:
- return error("Invalid record");
- }
+
+ SmallVector<uint64_t, 6> Buffer;
+ if (Error Err = upgradeDIExpression(Version, Elts, Buffer))
+ return Err;
MetadataList.assignValue(
- GET_OR_DISTINCT(DIExpression, (Context, makeArrayRef(Record).slice(1))),
- NextMetadataNo);
+ GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo);
NextMetadataNo++;
break;
}
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.reserve(N->getElements().size() + 1);
- const uint64_t Version = 2 << 1;
+ const uint64_t Version = 3 << 1;
Record.push_back((uint64_t)N->isDistinct() | Version);
Record.append(N->elements_begin(), N->elements_end());
int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
DwarfExpr.addFragmentOffset(Expr);
SmallVector<uint64_t, 8> Ops;
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Offset);
Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
DIExpressionCursor Cursor(Ops);
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
DwarfExpr.setMemoryLocationKind();
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
ExprCursor.take();
}
- // [Reg, Offset, DW_OP_plus] --> [DW_OP_breg, Offset].
- // [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset].
+ // [Reg, DW_OP_constu, Offset, DW_OP_plus] --> [DW_OP_breg, Offset]
+ // [Reg, DW_OP_constu, Offset, DW_OP_minus] --> [DW_OP_breg,-Offset]
// If Reg is a subregister we need to mask it out before subtracting.
- if (Op && ((Op->getOp() == dwarf::DW_OP_plus) ||
- (Op->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
- int Offset = Op->getArg(0);
- SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
- ExprCursor.take();
+ if (Op && Op->getOp() == dwarf::DW_OP_constu) {
+ auto N = ExprCursor.peekNext();
+ if (N && (N->getOp() == dwarf::DW_OP_plus ||
+ (N->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
+ int Offset = Op->getArg(0);
+ SignedOffset = (N->getOp() == dwarf::DW_OP_minus) ? -Offset : Offset;
+ ExprCursor.consume(2);
+ }
}
+
if (FBReg)
addFBReg(SignedOffset);
else
LocationKind = Unknown;
return;
}
- case dwarf::DW_OP_plus:
case dwarf::DW_OP_plus_uconst:
assert(LocationKind != Register);
emitOp(dwarf::DW_OP_plus_uconst);
emitUnsigned(Op->getArg(0));
break;
+ case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
- assert(LocationKind != Register);
- // There is no DW_OP_minus_uconst.
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(Op->getArg(0));
- emitOp(dwarf::DW_OP_minus);
+ emitOp(Op->getOp());
break;
case dwarf::DW_OP_deref: {
assert(LocationKind != Register);
DIExpressionCursor(ArrayRef<uint64_t> Expr)
: Start(Expr.begin()), End(Expr.end()) {}
+ DIExpressionCursor(const DIExpressionCursor &C)
+ : Start(C.Start), End(C.End) {}
+
/// Consume one operation.
Optional<DIExpression::ExprOperand> take() {
if (Start == End)
SmallVector<uint64_t, 9> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
// If we started with a pointer to the __Block_byref... struct, then
// DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in
// adding the offset if it's 0.
if (forwardingFieldOffset > 0) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(forwardingFieldOffset);
}
// for the variable's field to get to the location of the actual variable:
// DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0.
if (varFieldOffset > 0) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(varFieldOffset);
}
case dwarf::DW_OP_LLVM_fragment:
return 3;
case dwarf::DW_OP_constu:
- case dwarf::DW_OP_plus:
case dwarf::DW_OP_plus_uconst:
- case dwarf::DW_OP_minus:
return 2;
default:
return 1;
void DIExpression::appendOffset(SmallVectorImpl<uint64_t> &Ops,
int64_t Offset) {
if (Offset > 0) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Offset);
} else if (Offset < 0) {
- Ops.push_back(dwarf::DW_OP_minus);
+ Ops.push_back(dwarf::DW_OP_constu);
Ops.push_back(-Offset);
+ Ops.push_back(dwarf::DW_OP_minus);
}
}
Offset = 0;
return true;
}
- if (getNumElements() != 2)
- return false;
- if (Elements[0] == dwarf::DW_OP_plus ||
- Elements[0] == dwarf::DW_OP_plus_uconst) {
+
+ if (getNumElements() == 2 && Elements[0] == dwarf::DW_OP_plus_uconst) {
Offset = Elements[1];
return true;
}
- if (Elements[0] == dwarf::DW_OP_minus) {
- Offset = -Elements[1];
- return true;
+
+ if (getNumElements() == 3 && Elements[0] == dwarf::DW_OP_constu) {
+ if (Elements[2] == dwarf::DW_OP_plus) {
+ Offset = Elements[1];
+ return true;
+ }
+ if (Elements[2] == dwarf::DW_OP_minus) {
+ Offset = -Elements[1];
+ return true;
+ }
}
+
return false;
}
if (E)
OrigElements = E->getElements();
std::vector<uint64_t> Elements(OrigElements.size() + 2);
- Elements[0] = dwarf::DW_OP_plus;
+ Elements[0] = dwarf::DW_OP_plus_uconst;
Elements[1] = Offset;
std::copy(OrigElements.begin(), OrigElements.end(), Elements.begin() + 2);
E = DIExpression::get(getContext(), Elements);
; CHECK: !0 = !DIExpression()
; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref)
-; CHECK-NEXT: !2 = !DIExpression(DW_OP_plus, 3)
+; CHECK-NEXT: !2 = !DIExpression(DW_OP_constu, 3, DW_OP_plus)
; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
-; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
+; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7)
; CHECK-NEXT: !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
; CHECK-NEXT: !6 = !DIExpression(DW_OP_plus_uconst, 3)
!0 = !DIExpression()
!1 = !DIExpression(DW_OP_deref)
-!2 = !DIExpression(DW_OP_plus, 3)
+!2 = !DIExpression(DW_OP_constu, 3, DW_OP_plus)
!3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
-!4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
+!4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7)
!5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
!6 = !DIExpression(DW_OP_plus_uconst, 3)
!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
; DW_OP_deref should be moved to the back of the expression.
;
-; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32)
!6 = !DIExpression(DW_OP_deref, DW_OP_plus, 0, DW_OP_LLVM_fragment, 8, 32)
-; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref)
!7 = !DIExpression(DW_OP_deref, DW_OP_plus, 0)
-; CHECK: !DIExpression(DW_OP_plus, 1, DW_OP_deref)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 1, DW_OP_deref)
!8 = !DIExpression(DW_OP_plus, 1, DW_OP_deref)
; CHECK: !DIExpression(DW_OP_deref)
!9 = !DIExpression(DW_OP_deref)
--- /dev/null
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!8, !9}
+
+!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true)
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang (llvm/trunk 304286)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
+!2 = !DIFile(filename: "a.c", directory: "/")
+!3 = !{}
+!4 = !{!7}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: !DIExpression(DW_OP_constu, 42, DW_OP_minus)
+!6 = !DIExpression(DW_OP_minus, 42)
+!7 = !DIGlobalVariableExpression(var: !0, expr: !6)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
; CHECK: ![[HVAR:[0-9]+]] = distinct !DIGlobalVariable(name: "h",
; CHECK: ![[IMPORTS]] = !{![[CIMPORT:[0-9]+]]}
; CHECK: ![[CIMPORT]] = !DIImportedEntity({{.*}}entity: ![[HVAR]]
-; CHECK: ![[GEXPR]] = !DIExpression(DW_OP_plus, 1)
+; CHECK: ![[GEXPR]] = !DIExpression(DW_OP_plus_uconst, 1)
; CHECK: ![[H]] = {{.*}}!DIGlobalVariableExpression(var: ![[HVAR]])
@g = common global i32 0, align 4, !dbg !0
!160 = !DIFile(filename: "header.h", directory: "/Volumes/Sandbox/llvm")
!161 = !{!"header2.h", !"/Volumes/Sandbox/llvm"}
!162 = !{i32 1, !"Debug Info Version", i32 3}
-!163 = !DIExpression(DW_OP_plus, 20, DW_OP_deref, DW_OP_plus, 4, DW_OP_deref, DW_OP_plus, 24)
-!164 = !DIExpression(DW_OP_deref, DW_OP_plus, 24)
-!165 = !DIExpression(DW_OP_deref, DW_OP_plus, 28)
+!163 = !DIExpression(DW_OP_plus_uconst, 20, DW_OP_deref, DW_OP_plus_uconst, 4, DW_OP_deref, DW_OP_plus_uconst, 24)
+!164 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 24)
+!165 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 28)
!5 = !{i32 2, !"Dwarf Version", i32 4}
!6 = !{i32 2, !"Debug Info Version", i32 3}
!7 = !{i32 1, !"PIC Level", i32 2}
- !8 = !DIExpression(DW_OP_plus, 8, DW_OP_stack_value)
+ !8 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value)
!9 = distinct !DISubprogram(name: "fn1", scope: !1, file: !1, line: 7, type: !10, isLocal: false, isDefinition: true, scopeLine: 7, isOptimized: true, unit: !0, variables: !11)
!10 = !DISubroutineType(types: !3)
!11 = !{!12}
; Check that the location of the ASAN instrumented __block variable is
; correct.
-; CHECK: !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24)
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
!19 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!20 = !DIDerivedType(tag: DW_TAG_member, name: "__size", size: 32, align: 32, offset: 160, file: !1, scope: !5, baseType: !19)
!21 = !DIDerivedType(tag: DW_TAG_member, name: "x", size: 32, align: 32, offset: 192, file: !1, scope: !5, baseType: !19)
-!22 = !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24)
+!22 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24)
!23 = !DILocation(line: 4, column: 15, scope: !4)
!24 = !DILocation(line: 4, column: 3, scope: !4)
!25 = !DILocation(line: 5, column: 3, scope: !4)
!17 = !{!18}
!18 = !DISubrange(count: 4)
!19 = !DILocation(line: 4, column: 13, scope: !9)
- !20 = !DIExpression(DW_OP_plus, 1, DW_OP_minus, 1)
+ !20 = !DIExpression(DW_OP_plus_uconst, 1, DW_OP_constu, 1, DW_OP_minus)
!21 = !DILocation(line: 4, column: 7, scope: !9)
!22 = !DILocation(line: 5, column: 9, scope: !9)
!23 = !DILocation(line: 5, column: 18, scope: !9)
!66 = !DILocation(line: 2, column: 20, scope: !8)
!67 = !DILocation(line: 2, column: 21, scope: !8)
!68 = !DILocalVariable(name: "block", line: 2, scope: !8, file: !5, type: !25)
-!69 = !DIExpression(DW_OP_deref, DW_OP_plus, 32)
+!69 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32)
!70 = !DILocation(line: 2, column: 9, scope: !8)
!71 = !DILocation(line: 2, column: 23, scope: !72)
!72 = distinct !DILexicalBlock(line: 2, column: 21, file: !1, scope: !8)
!106 = !DILocation(line: 40, scope: !42)
!107 = !DIFile(filename: "llvm/tools/clang/test/CodeGenObjC/debug-info-block-captured-self.m", directory: "")
!108 = !{i32 1, !"Debug Info Version", i32 3}
-!109 = !DIExpression(DW_OP_plus, 32, DW_OP_deref)
-!110 = !DIExpression(DW_OP_plus, 32, DW_OP_deref)
+!109 = !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref)
+!110 = !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref)
!108 = !DILocation(line: 61, scope: !36)
!109 = !DILocation(line: 62, scope: !36)
!110 = !{i32 1, !"Debug Info Version", i32 3}
-!111 = !DIExpression(DW_OP_deref, DW_OP_plus, 32)
+!111 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32)
; Capture(buf);
; }
; }
-; The interesting part is !DIExpression(DW_OP_minus, 400)
+; The interesting part is !DIExpression(DW_OP_constu, 400, DW_OP_minus)
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
!14 = !{i32 2, !"Debug Info Version", i32 3}
!15 = !{!"clang version 3.8.0 (trunk 248518) (llvm/trunk 248512)"}
!16 = !DILocation(line: 5, column: 3, scope: !4)
-!17 = !DIExpression(DW_OP_minus, 400)
+!17 = !DIExpression(DW_OP_constu, 400, DW_OP_minus)
!18 = !DILocation(line: 5, column: 7, scope: !4)
!19 = !DILocation(line: 6, column: 11, scope: !4)
!20 = !DILocation(line: 6, column: 3, scope: !4)
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10)
-!13 = !DIExpression(DW_OP_minus, 1, DW_OP_stack_value)
+!13 = !DIExpression(DW_OP_constu, 1, DW_OP_minus, DW_OP_stack_value)
!14 = !DILocation(line: 1, column: 13, scope: !7)
!15 = !DILocation(line: 2, column: 11, scope: !7)
!16 = !DILocation(line: 2, column: 3, scope: !7)
; }
; CHECK: ![[ZZZ:.*]] = !DILocalVariable(name: "zzz",
-; CHECK: ![[ZZZ_EXPR:.*]] = !DIExpression(DW_OP_deref, DW_OP_minus, 400)
+; CHECK: ![[ZZZ_EXPR:.*]] = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus)
; CHECK: DBG_VALUE {{.*}} ![[ZZZ]], ![[ZZZ_EXPR]]
%struct.S = type { [100 x i32] }
!20 = !{i32 2, !"Debug Info Version", i32 3}
!21 = !{!"clang version 3.8.0 (trunk 254107) (llvm/trunk 254109)"}
!22 = !DILocation(line: 8, column: 9, scope: !12)
-!23 = !DIExpression(DW_OP_deref, DW_OP_minus, 400)
+!23 = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus)
!24 = !DILocation(line: 8, column: 28, scope: !12)
!25 = !DIExpression()
!26 = !DILocation(line: 9, column: 10, scope: !12)
!15 = !DISubprogram(name: "<(lambda at test.ii:87:58)>", scope: !0, file: !1, line: 27, type: !6, isLocal: false, isDefinition: false, scopeLine: 27, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true, templateParams: !2)
!16 = distinct !DILocation(line: 99, column: 21, scope: !17)
!17 = !DILexicalBlockFile(scope: !5, file: !1, discriminator: 2)
-!18 = !DIExpression(DW_OP_plus, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 32)
+!18 = !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 32)
!1 = !{!2}
!2 = !DIGlobalVariableExpression(var: !3, expr: !4)
!3 = distinct !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true, type: !6)
-!4 = !DIExpression(DW_OP_plus, 4)
+!4 = !DIExpression(DW_OP_plus_uconst, 4)
!5 = !DIFile(filename: "<stdin>", directory: "/")
!6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
; CHECK: [[AVAR]] = !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true)
; CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BVAR:![0-9]+]], expr: [[EXPR:![0-9]+]])
; CHECK: [[BVAR]] = !DIGlobalVariable(name: "b", scope: null, isLocal: false, isDefinition: true)
-; CHECK: [[EXPR]] = !DIExpression(DW_OP_plus, 4)
+; CHECK: [[EXPR]] = !DIExpression(DW_OP_plus_uconst, 4)
!llvm.module.flags = !{!4, !5}
ret void, !dbg !32
}
-; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus, 0)
-; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus, 0)
-; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_plus, 0, DW_OP_stack_value)
-; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value,
+; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 0)
+; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus_uconst, 0)
+; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 0, DW_OP_stack_value)
+; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value,
; CHECK-SAME: DW_OP_LLVM_fragment, 0, 32)
-; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value)
+; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value)
; Function Attrs: nounwind readnone
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
!17 = !{!18}
!18 = !DILocalVariable(name: "entry", scope: !14, file: !1, line: 6, type: !4)
!19 = !DILocation(line: 6, column: 17, scope: !14)
-!20 = !DIExpression(DW_OP_plus, 0)
+!20 = !DIExpression(DW_OP_plus_uconst, 0)
!21 = !DILocation(line: 11, column: 1, scope: !14)
!22 = distinct !DISubprogram(name: "scan", scope: !1, file: !1, line: 4, type: !15, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !17)
!23 = !DILocation(line: 6, column: 17, scope: !22)
; CHECK-DAG: ![[VAR_ARG]] = !DILocalVariable(name: "zzz"
; 100 aligned up to 8
-; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_minus, 104)
+; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_constu, 104, DW_OP_minus
; CHECK-DAG: ![[VAR_LOCAL]] = !DILocalVariable(name: "xxx"
-; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_minus, 208)
+; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_constu, 208, DW_OP_minus
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
!13 = !DILocation(line: 5, column: 3, scope: !6)
!14 = !DILocation(line: 6, column: 3, scope: !6)
-; CHECK-DAG: ![[X1_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_minus, 4)
-; CHECK-DAG: ![[X2_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_minus, 8)
+; CHECK-DAG: ![[X1_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_constu, 4, DW_OP_minus)
+; CHECK-DAG: ![[X2_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_constu, 8, DW_OP_minus)
!15 = !DIExpression(DW_OP_deref)
!16 = !DILocation(line: 5, column: 7, scope: !6)
!17 = !DILocation(line: 8, column: 3, scope: !6)
!21 = !DILocation(line: 10, column: 1, scope: !22)
!22 = !DILexicalBlockFile(scope: !6, file: !1, discriminator: 1)
!23 = !DIExpression()
-!24 = !DIExpression(DW_OP_minus, 42)
+!24 = !DIExpression(DW_OP_constu, 42, DW_OP_minus)
EXPECT_TRUE(DIExpression::get(Context, None));
// Valid constructions.
- EXPECT_VALID(dwarf::DW_OP_plus, 6);
EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6);
+ EXPECT_VALID(dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus);
EXPECT_VALID(dwarf::DW_OP_deref);
EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7);
- EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref);
- EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6);
EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 3, 7);
- EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6,
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6,
dwarf::DW_OP_LLVM_fragment, 3, 7);
// Invalid constructions.
EXPECT_INVALID(~0u);
- EXPECT_INVALID(dwarf::DW_OP_plus);
+ EXPECT_INVALID(dwarf::DW_OP_plus, 0);
EXPECT_INVALID(dwarf::DW_OP_plus_uconst);
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment);
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3);
- EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus, 3);
+ EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus_uconst, 3);
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_deref);
#undef EXPECT_VALID