summaryrefslogtreecommitdiff
path: root/lib/Bitcode
diff options
context:
space:
mode:
authorFlorian Hahn <florian.hahn@arm.com>2017-06-14 13:14:38 +0000
committerFlorian Hahn <florian.hahn@arm.com>2017-06-14 13:14:38 +0000
commit50963b3b75627a63ddceb22ef2b80b5c16c0a028 (patch)
treee95cc2f1628aa29735f47754252c2df7f19b5589 /lib/Bitcode
parent3e4134fdf135182419fa5ddc8a2a5ab4abdab480 (diff)
Align definition of DW_OP_plus with DWARF spec [3/3]
Summary: This patch is part of 3 patches that together form a single patch, but must be introduced in stages in order not to break things. The way that LLVM interprets DW_OP_plus in DIExpression nodes is basically that of the DW_OP_plus_uconst operator since LLVM expects an unsigned constant operand. This unnecessarily restricts the DW_OP_plus operator, preventing it from being used to describe the evaluation of runtime values on the expression stack. These patches try to align the semantics of DW_OP_plus and DW_OP_minus with that of the DWARF definition, which pops two elements off the expression stack, performs the operation and pushes the result back on the stack. This is done in three stages: • The first patch (LLVM) adds support for DW_OP_plus_uconst. • The second patch (Clang) contains changes all its uses from DW_OP_plus to DW_OP_plus_uconst. • The third patch (LLVM) changes the semantics of DW_OP_plus and DW_OP_minus to be in line with its DWARF meaning. This patch includes the bitcode upgrade from legacy DIExpressions. Patch by Sander de Smalen. Reviewers: echristo, pcc, aprantl Reviewed By: aprantl Subscribers: fhahn, javed.absar, aprantl, llvm-commits Differential Revision: https://reviews.llvm.org/D33894 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305386 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Bitcode')
-rw-r--r--lib/Bitcode/Reader/MetadataLoader.cpp123
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp2
2 files changed, 93 insertions, 32 deletions
diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp
index ee2fe2a0cc1..b1504a8034e 100644
--- a/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -407,6 +407,11 @@ void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) {
} // 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;
@@ -533,6 +538,88 @@ class MetadataLoader::MetadataLoaderImpl {
}
}
+ /// 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();
@@ -590,11 +677,6 @@ public:
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;
@@ -1551,34 +1633,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
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;
}
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index d5879fec95c..e679424bf1f 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1663,7 +1663,7 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
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());