When importing an alloca whose array size is not a constant 1,
import the alloca's element type as an opaque-array struct
instead of a real C array, matching the treatment that other
array-typed values already get. This keeps the rest of the
emitted code free of array rvalues that would otherwise decay to
pointers.
Drop the previous workaround that always reported a struct byte
size of 0 (with a TODO referencing the missing DataLayout) and use
DataLayout::getStructLayout to get the real struct size. The
DataLayout is now available via the field added in a previous
commit.
Use model-sized pointers on function and call boundaries. These
are necessary for type checking, because llvm::DataLayout at the
moment is not guaranteed to have the same pointer size as the
model, due to quirks of how the DataLayout is initialised. The
function/call boundary is exactly where the model pointer size
becomes observable, so that's where the explicit cast is emitted.
Now that we need the llvm::DataLayout for e.g. computing pointer
sizes, caching pointer types becomes risky: different DataLayouts
coming from different LLVM Modules could disagree on the pointer
size, and securing against this would require clearing the caches
at every call to import.
Given that the caches in practice were not caching operations that
are supposed to be slow, just drop all the type caches to simplify
the codebase.
Replace the standalone PointerSize field with a pointer to the
function's llvm::DataLayout, and read the pointer size off the
DataLayout when needed. This keeps the importer aligned with what
LLVM thinks the pointer size is, instead of relying on an external
source of truth that may go stale.
Use llvm::DataLayout to compute helper struct layouts in the
Clifter, mirroring what HelpersToHeader does. The layout query
replaces a couple of hand-rolled offset/size computations and
keeps the importer in sync with what LLVM and the helpers header
believe about each helper struct.
When importing an llvm::ArrayType, emit a Clift StructType with the
OpaqueType rank in its handle and a single i8 array field of the
right byte size, instead of a real array type. This avoids
exposing C array types as rvalues in the generated code, which is
a foot-gun because array rvalues immediately decay to pointers,
and provides a single name (via the existing OpaqueType infra) for
arrays of equal byte size.
Rework the GEP-importing logic to handle the i8-typed,
byte-strided GEPs produced by ArithmeticToGEP (and natively used
elsewhere) in addition to the structured ones it already supported.
Indices are now interpreted as byte offsets and the importer walks
the model type tree at byte granularity to materialise the right
sequence of field/element accesses.
Drop the !revng.variable_type metadata and the matching helpers,
along with the only place in the Clifter that still consumed them.
After the previous LVB cleanup nothing emits this metadata, and the
model variable type can be reconstructed from the alloca's array
type alone.
Value types is the set of non-array object types. These types are
assignable, can be used as function parameters, and as return types
(along with void), and in other scenarios where the type must have usual
value-like behaviour with no weirdness (such as array decay).
`mlir::Type` is now used as the default C++ type for representing all
MLIR types, even when `ValueType` would be a valid constraint, unless
doing so provides a clear benefit in that specific context.
* PrimitiveType is now an interface.
* VoidKind is now VoidType.
* FloatKind is now FloatType.
* The integer kinds are now IntegerType with IntegerKind.
* DecayOp - array or function to pointer decay. Not shown in C.
* BitCastOp - bit-preserving conversion. Emitted as bit_cast if
necessary.
* ExtendOp - zero- or sign-extending conversion from any integer type to
any wider integer type.
* TruncateOp - truncating conversion from any integer type to any
narrower integer type.
* PtrResizeOp - resizes a pointer without changing its pointee type.
Handles were previously assigned in the model name import pipe, but as
they are not expected to change often, they can be improted in the
Clifter. Additionally, in some cases it may be desirable to emit C
using generated names instead of those imported from the model, in which
case no handles would be available.
* Make the following private headers public:
* Lift/CPUStateAccessAnalysisPass.h
* Lift/CSVOffsets.h
* Lift/PTCDump.h
* Lift/VariableManager.h
* Move from revngSupport to revngLift:
* IRAnnotators.{h,cpp}
* SelfReferencingDbgAnnotationWriter.{h,cpp}
* Move from revngSupport to revngModel:
* FunctionTags.{h,cpp}
* ProgramCounterHandler.{h,cpp}
* Move from revngSupport to revngRecompile:
* OriginalAssemblyAnnotationWriter.{h,cpp}