Also provide a tryExtValue() API like APInt did in D139683
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
revert the format.
Original APSInt.h doesn't comply with clang-format. Maybe change it in another patch
llvm/unittests/ADT/APSIntTest.cpp | ||
---|---|---|
88 | why can't a i128 -7 be represented as a i64 -7? |
llvm/unittests/ADT/APSIntTest.cpp | ||
---|---|---|
88 | APInt(128, -7) == (uint64)-7, there are 64 leading zeros and thus is a actually a huge positive number. I added two more tests to make this clear. |
llvm/include/llvm/ADT/APSInt.h | ||
---|---|---|
94 | The comment near getMinSignBits says that it is deprecated (and "use getSignificantBits() instead"). return isSigned() ? isSignedIntN(64) : isIntN(63); |
llvm/include/llvm/ADT/APSInt.h | ||
---|---|---|
104 | You don't need the constructor. getExtValue()should work. |
llvm/include/llvm/ADT/APSInt.h | ||
---|---|---|
104 | Yes I do, otherwise the static type of the two branch don't match, as discussed here: https://reviews.llvm.org/D139683 llvm/include/llvm/ADT/APInt.h:1500:36: error: incompatible operand types ('uint64_t' (aka 'unsigned long') and 'const std::nullopt_t') return (getActiveBits() <= 64) ? getZExtValue() : std::nullopt; ^ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~ |
After this patch the semantics of getExtValue changed and thus broke clang. @pcc Would you mind take a look if the modification works for clang.
clang/lib/CodeGen/CGDebugInfo.cpp | ||
---|---|---|
5386 ↗ | (On Diff #485328) | I think we actually want the existing behavior here. Values embedded in debug info aren't really signed or unsigned; they're interpreted by the debugger based on the type of the value. Maybe it makes sense to add a new APSInt API for that? Or I guess we could explicitly write out Init.getInt().isSigned() ? Init.getInt().getSExtValue() : Init.getInt().getZExtValue(); if we can't think of a reasonable name for the new API... |
clang/lib/CodeGen/CGDebugInfo.cpp | ||
---|---|---|
5386 ↗ | (On Diff #485328) | I have no problem with this proposed new API, we may even name it uint64_t tryInt64Representaiton. My main concern is that returning a value whose static type is unsigned while semantics can be signed OR unsigned is a bit inconsist. I will use something like Init.getInt().isSigned() ? Init.getInt().getSExtValue() : Init.getInt().getZExtValue(); for now. |
Hello, it appears this patch causes a crash when I analyze this reproducer, with Z3 enabled. In the case shown here, the analyzer finds that 'f' to the call a(f) is uninitialized, and then is attempted to be refuted through SMTConv, leading to the assertion.
If I modify the below code to not use isRepresentableByIn64(), or use 'assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");' instead, I do not see the crash.
clang --analyze -Xclang -analyzer-config -Xclang crosscheck-with-z3=true --target=x86_64-redhat-linux case.c
void a(int); typedef struct { int b; } c; c *d; void e() { (void)d->b; int f; a(f); }
The assert ...
clang-16: ../include/llvm/ADT/APSInt.h:99: int64_t llvm::APSInt::getExtValue() const: Assertion `isRepresentableByInt64() && "Too many bits for int64_t"' failed.Program received signal SIGABRT, Aborted.
Thanks for helping identifying the bug.
This is not a problem in this patch, the semantics of getExtValue changed in this patch as carefully discussed here.
To summarize, we believe its not reasonable to carry out ext for (signed)(int64::Max + 1). Although it's still 64 bit, the returned value would be interpreted as int64::Min instead of a large positive integer. This behavior was allowed before.
To provide a fix for this problem, this patch provides a better way to determine if the extension is possible isRepresentableByInt64, I would recommend replacing if (LLVM_UNLIKELY(Int.getBitWidth() > 64u)) in Z3Solver.cpp:732 with if (LLVM_UNLIKELY(!Int.isRepresentableByInt64())).
Thanks @Peter. I tried that, and the crash is resolved. Submitted https://reviews.llvm.org/D142627 for review.
The comment near getMinSignBits says that it is deprecated (and "use getSignificantBits() instead").
There are also isSignedIntN and isIntN, which can be useful: