Commit Graph

6113 Commits

Author SHA1 Message Date
Pietro Fezzardi 5b57a206d0 ASTBuildAnalysis: handle pointer operands from DLA
When DLA is activated, a larger variety of combinations between integers
and pointers operands need to be handled when emitting C code from LLVM
Instructions.
This commit removes some assertions that do not hold anymore about some
operands not being pointers, handles a set of new cases with strange
mixtures of pointer and integer operands, and introduces a fail path for
cases that are not handled when emitting code based on DLA results.
2021-02-03 12:37:24 +01:00
Pietro Fezzardi 6ad6d5294d Fix getPointedLayouts for struct types
Before this commit, we assumed that given a Value V, if only a single
entry was found for in ValueLayouts, it meant that is was a scalar type.

This assumption was wrong, because it could be a struct type for which
we didn't have information about memory access for all fields but one.
This caused some struct type to be wrongly identified as scalar types.

This commit fixes the issue.
2021-02-03 12:13:14 +01:00
Pietro Fezzardi 4b50946d60 DLACreateIntraProcedualTypes: create less pointers
Before this commit, the creation of layouts in the DLA was very
aggressive, treating almost every instruction as if it could be an
address (hence creating a layout for it).

This commit adds assertions and narrows down the number of cases where
an instruction is actually considered an address.
Specifically, the following kinds of instructions are not considered
addresses anymore:
  - Mul
  - SDiv
  - UDiv
  - SRem
  - URem
  - AShr
  - LShr
  - Shl
  - And
  - Xor
  - Or
2021-02-03 12:07:28 +01:00
Pietro Fezzardi 7a1b11a83d DecompilationHelpers: improve int->ptr casts
Before this commit, we assumed integer-to-pointer casts were only
widening, never narrowing.
Turns out this is not true. For instance, narrowing casts happen when
decompiling s390x code.

With this commit, the decompiler can handle that case gracefully.
2021-02-03 12:03:29 +01:00
Pietro Fezzardi 904aab0f6f LayoutTypePtr: drop friend struct std::less
This was necessary before defaulting operator<=>, now it's not necessary
anymore.
2021-02-03 12:02:25 +01:00
Pietro Fezzardi dc84daf7e8 DLATypeSystem: add assertion on mergeNodes
The mergeNodes API is not guaranteed to work properly if the 2 merged
nodes are the same.
This commit adds an assertion to rule this situation out.
2021-02-03 12:00:04 +01:00
Pietro Fezzardi 42b9fb97e7 Drop static storage specifier for globals 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 4cf69e8edd ASTBuildAnalysis: fix emission of comparison ops 2021-02-02 11:23:53 +01:00
Pietro Fezzardi c02db52709 IRASTTypeTranslation: fix bug in getPointedLayouts 2021-02-02 11:23:53 +01:00
Pietro Fezzardi ad70251a7f SCEVBaseAddressExplorer: fix exploration of Values
A logical bug prevented to properly identify some leaf Values in SCEVs
as base addresses, restricting such Value leaves to only be CallInst to
isolated Functions.
This commit fixes this bug and enables to identify base addresses that
are not CallInst.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi b33e9385fe ASTBuildAnalysis: add draft of member accesses
This commit is just a skeleton. In order to actually build those member
accesses, we still need to compute the proper nested dla::Layouts for
which we want to emit those member accesses.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 6c0cc326a4 Fix comment 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 4767fa63c3 Fixed emission for local_sp and scev_barrier
This commit fixes a bug due to interacting behaviors between
MarkForSerialization, AddSCEVBarrierPass, and the emission in C of calls
to revng_init_local_sp.

These interacting behaviors caused the following quirks:
- At the beginning of Functions that contained a call to
  `revng_init_local_sp()`, that call was actually emitted twice.
  The first time was due to the actual call to `revng_init_local_sp()`,
  while the second was due to the first call being wrapped from a call
  to `revng_scev_barrier_*`.
  Now we properly emit only one call.
- The original call to `revng_init_local_sp()` was supposed to generate
  a local variable, to be used in various places across the function.
  However, due to the fact that the call was not properly labeled by
  MarkForSerialization, there was no local variable, causing calls to
  `revng_init_local_sp()` to be scattered around the body of the
  functions, follwed by various arithmetic operations.
  This behavior has been fixed as well, and we now emit the local
  variable correctly.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi ba0e57e956 DeclCreator: unify type mapping 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 2485cd2c8b DLAHelpers: relax assumptions on ExtractValueInst
Before this commit, the DLA code made very strong assumptions about
Functions that returned struct types.
In particular, calls to such Functions were expected to have at most a
number of uses equal to the number of fields of the returned struct.
Moreover, such uses were only expected to be ExtractValueInst.

Now, we still assume that such uses are ExtractValueInst, but we don't
make any strong assumption on their number anymore.

This makes the DLA code less reliant on specific form of LLVM IR, so we
can also drop -gvn-hoist from the decompilation test pipeline.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 56fe5c95c3 New Typeable type
This type represents all llvm constructs to which we may want to
associate a type.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 821b430f40 Collapse FunctionDecls map into GlobalDecls map 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 6de169e138 MarkForSerialization: new LatticeElement
This commit introduces a new LatticeElement for the
MarkAnalysis::Analysis MonotoneFramework.

Before this it used a IntersectionMonotoneSet.
This commit extends the set transforming it into a map, that holds the
set of Instructions with side-effects that taint each pending
instruction.

This is not used yet. The behavior is identical to the old one.
It will be used in future commits to prevent serialization when
possible, to increase the quality of emitted C code, thanks to the fact
that serializing less instructions means less local variables in C.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 5e433cd7b3 Switch tests order, anticipating torture.
This makes faster to run all the tests, because the heavier tests are
run first.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 3f1ee6ea64 Stub of DLA integration in Clang AST emission 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 3b3dbc3a8b Add end-to-end tests for AddSCEVBarrierPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 23a338dfb7 Add end-to-end tests for various passes
This commit adds end-to-end tests for the following passes:
  -promote-stack-pointer
  -adjust-stack-pointer
  -dla
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 7987eccecd ASTBuildAnalysis: handle nested InsertValueInst 2021-02-02 11:23:53 +01:00
Pietro Fezzardi aecfd8c7f6 ASTBuildAnalysis: handle undefs in InserValueInst 2021-02-02 11:23:53 +01:00
Pietro Fezzardi d01aa3b0fb Move SCEVBaseAddressExplorer to its own file
This enables using it in the decompilation backend.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 088015e11c Forward SCEV and DLA results to decompilation 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 3cbd8f2254 Create AddSCEVBarrierPass
This `FunctionPass` uses the results of `MarkForSerializationPass`, if
present, to wrap some instructions into calls to `revng_scev_barrier_*`
functions.

`revng_scev_barrier_*` functions have names that are deterministically
constructed from the type they wrap.
They have the semantics of an identity function, but we don't provide
the body, so that LLVM's ScalarEvolution Analysis cannot see through
them.

At the moment, the inserted function calls are not manipulated anywhere
else in the codebase, but we plan to use this mechanism in the
decompilation pass to prune the expressions that are converted to
pointer arithmetic.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 23d2f19211 Remove old TODO 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 9d1d6afe6e MarkForSerialization: extract into its own Pass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi a9e171e4ed UnitTest: update cmake file to match revng 2021-02-02 11:23:53 +01:00
Pietro Fezzardi f642a0983c Decompiler: make NDuplicates a const reference 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 8be05522e6 MarkForSerialization: improve const-correctness 2021-02-02 11:23:53 +01:00
Pietro Fezzardi d1ada19ca6 CDecompilerBeautify: remove unused Mark parameter 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 2ff7044bb9 Decompiler: forward-declare types coming from DLA
This commits enable the emission of rich types associated with function
signatures. This types are forward-declared in the decompiled C code
before the definition of each decompiled function that uses them.

The types we emit for now are the types that the DLA is able to compute
(if any) for the return values and the arguments of the function.

Such types are not yet used in the body of the function, nor in the
function declaration. These are the next steps to come.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi b9c17362dd Decompiler: handle emission of logical operators
Before this commit, logical operators (&&, ||, !) were never emitted in
C. Bitwise operators were used instead (&, |, ~), relying on the
implicit equivalence of meaning.

This commit enables the emission of logical operators when the operands
are boolean types, making the emitted C more readable.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 476064d855 [DLA] kill structural deduplication of Layouts
Before this commit, the MakeLayout step of the DLA used to deduplicate
structurally equal Layouts. This has turned out to be wrong when going
forward with the emission of types in C.
Being able to tell apart two different types that are structurally equal
is important for the emission of C types. Throwing this information away
with deduplication is bad. This commit disables such deduplication.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi e0f9401ff8 ADT: add HeterogeneousPtrCompare template class
This is a utility class useful to make std::set<std::unique_ptr<T>>
searchable with raw pointers, by using
std::set<std::unique_ptr<T>, HeterogeneousPtrCompare<T>> instead.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi d6c8214d52 Decompiler: improve handling of command line flags
Handling of command line options that specify paths for output files
have been improved in the following ways:
- If the CDecompilerPass is not default-constructed, it already has a
  reference to the stream where outputs must be written. In this case,
  it is wrong to use a command line option to specify the output
  directory. If this happens the program is now able to detect it and to
  terminate with an error.
- If some of the specified paths is not found or has the wrong
  permission, the program fails early.
- On program failure because of one of the above safety checks, the
  program terminates with an informative error message.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi b59c239401 Decompiler: make all command line options Optional
This means that they can be specified only once on the command line.
If they are specified more than once, the program fails with an
informative error.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi ba3fb13dd6 CDecompilerPass: avoid removing calls to newpc
We now have a dedicated pass for that
2021-02-02 11:23:53 +01:00
Pietro Fezzardi ca999a7c3c Add DeclCreator class to unify forward declaration
Before this commit, the logic to generate all the emitted C forward
declarations (types, global variables, and functions) that has to be
printed before each decompiled function was scattered across three
classes: FuncDeclCreationAction, TypeDeclCreationAction, and
GlobalDeclCreationAction.

These are all gone now, because the scattered logic was very confusing
to follow. Now we only have a single class that takes care of
declarations with global scope: DeclCreator.

Thanks to this, I was able to drop a bunch of useless layers of software
engineering used to shape the creation of the declaration as if it was
some kind of clang ASTConsumer, which is pointless.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 1e825a8201 Create IRASTTypeTranslator class
This class handles the creation of type declarations in clang's AST, and
holds the relationships between llvm Types and Values with those clang's
type declarations.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi cbbbdf660f [DLA] propagate DLA results to CDecompilerPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 44564c2ba7 [DLA] export layouts to DLAPass 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 52d0d9aeb2 [DLA] Move Layouts declarations in separate files
This is a preliminary step for allowing DLAPass to export the computed
layouts as analysis results.
2021-02-02 11:23:53 +01:00
Pietro Fezzardi c553965b62 CDecompilerPass: addUsedIfAvailable<DLAPass>() 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 84d9dd1533 ASTBuildAnalysis: enable print negative literals 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 59076db31b [DLA] Avoid instance links for unsupported offsets
This commit prevents the creation of instance links for offsets that we
don't support yet, during the CreateIntraProceduralTypes DLAStep.
This makes possible to avoid explicitly handling those cases in many
DLASteps, such as ComputeUpperMemberAccess,
ComputeNonInterferingComponents, and DLAMakeLayouts.

The offsets that are not supported yet are:
- all negative offsets
- all strided offsets with non-strictly-positive stride values
- all strided offsets with non-strictly-positive stride values
- all strided offsets with known negative trip-count

Some beneficial side-effects of avoiding the creation of such links are:
- the total number of edges on the graph is reduced, reducing the worst
  case depth of most visits
- it's impossible to create types with null or negative size (that we
  wouldn't know how to emit in C)
2021-02-02 11:23:53 +01:00
Pietro Fezzardi 730854aa1c [DLA] Add CreateNonInterferingComponents DLAStep 2021-02-02 11:23:53 +01:00
Pietro Fezzardi 6ae374b5f0 [DLA] Add InterferingInfo to LayoutTypeSystemNode
This is a flag used to mark a given `LayoutTypeSystemNode`.
It represents the fact that the children nodes are either all
interfering with each other, non-interfering with each other, or
unknown.

This information will be filled-in by the
`ComputeNonInterferingComponents` step, and will be used from the
`MakeLayouts` step to decide if the children of the node will be emitted
as fields of a union (interfering) or fields of a struct
(non-interfering).
2021-02-02 11:23:53 +01:00