Sometimes code performs an indirect jump without changing the value of
the PC. In most cases this is due to non-code or some other faulty
situation, but it is in principle possible that an instruction performs
an indirect branch to its own address.
This commit ensures that this situation does not end up in an hard
failure.
Now extractvalue instruction are replaced by dedicated
OpaqueExtractValue custom opcode, that prevents LLVM from doing strange
things with extractvalues during optimizations (such as e.g. sinking).
This is important since extractvalue instructions and struct-typed
values in general in our LLVM IR are not real first-class citizens, but
only a byproduct of the binary lifting process, and they actually
represent bundles of registers that are returned from isolated
functions.
This commit enables to emit accesses with the square bracket array
access operator on pointers.
This is accomplished by adding an additional mandatory argument to
ModelGEP (AND NOT to ModelGEPRef) to represent this case.
MakeModelGEPPass is updated to take this into account, together with all
the other passes that handle ModelGEPs.
This commit teaches getExpectedModelType about the fact that various
bitwise operations are only allowed to have integer operands.
It also updates VMA, which uses getExpectedModelType, to take this
into account.
This commit introduces modelType, which supersedes `llvmIntToModelType`
in order to better handle translation of LLVM types into model types
after introduction of opaque pointer types. The main differences is
that `modelType` accepts the `Value` (instead of just the `Type`), so it
can better handle `AllocaInst` and `GlobalVariable`, which provide
information about the pointee.
This commit drops the `CallToLifted` tag in favor of a
`getCallToIsolatedFunction` function which checks if the call has the
`IsolatedFunction` tag. The function also assumes that indirect calls
are calls to lifted functions.
This commit changes MakeSegmentRefPass so that it's now a ModulePass and
it uses the binary to detect integer constants that represent the
address of strings.
When it detects address of constant strings, instead of injecting calls
to SegmentRef, we now inject calls to cstringLiteral, so that we can
later emit them as inline string literals in C.
In segmentRef we use integer type meaning address in memory, so we
generate segmentRef function with non-pointer type. For cstringLiteral
function we need real pointer type of operand.
Save MetaAddress, size, offset and original type for every
cstringLiteral call in metadata as we do for segmentRef calls.
For cstringLiteral "revng.cstring_literal" metadata name is used.
StringLiteralPool needs tuple of address, size, offset and type to
keep distinct string decorator functions for each string. This tuple is
represented by StringLiteralPoolKey struct.
Pipe for MakeSegmentRefPass needs to be defined explicitly, because
additional wrapper passes are required in MakeSegmentRef:
1. LoadModelWrapperPass
2. LoadBinaryWrapperPass
MakeSegmentRefPass requires access to RawBinaryView to detect cstring
literals in binary.
Fix printed command in MakeSegmentRefPipe
This printed command might not work. @ale commented it will be replaced
with `revng pipe run-pipe` once we will have it.
Update IRHelpers to new revng API
Switch String and Namespace arguments in getUniqueString
This commit works around a quirk of
`llvm::ConstantDataArray::getString`, which returns a
`llvm::ConstantAggregateZero` for empty strings.
This quirk caused assertions in the previous implementation when passing
an empty `String` to `getUniqueString`.
Using an empty namespace causes the creation of a named metadata with an
empty string as name.
`llvm::verifyModule` does not check for that, so the `Module` still
verifies, but the on-disk serialization generated by `AsmPrinter.cpp`
prints `"empty name"` instead of the metadata name, and if the
serialized `Module` is then reparsed it parses succesfully but it does
not verify anymore.
`getUniqueString` returns a dedup'd char array `GlobalVariable` given a
string. We used to rely on named metadata to dedup them. However, this
lead to issues with `LLVMContainer` cloning and linking.
The new implementation uses the name of the variable as the
de-decuplication key, circumventing the problem entirely and improving
performance.