Commit Graph

80 Commits

Author SHA1 Message Date
Robert Marsh
8087cb5040 C++: add CopyValueInstruction for StmtExpr result 2019-04-05 11:27:19 -07:00
Robert Marsh
427b853077 C++: add another test case for IR stmtexpr 2019-04-04 10:55:27 -07:00
Robert Marsh
f2fbdac31b C++: add support for GNU StmtExpr in IR 2019-04-04 10:51:06 -07:00
Dave Bartolomeo
e25c578011 C++: Use #if 0 instead of comment to exclude broken test case. 2019-03-25 11:10:13 -07:00
Dave Bartolomeo
2e752f48ff C++: Add more Lambda IR test cases
New tests for mixed =/& captures and for captures with initializers
2019-03-25 11:05:53 -07:00
Dave Bartolomeo
d20e5bc69c C++: IR construction for lambda expressions
The IR construction code wasn't handling lambda expressions, so I added `TranslatedLambdaExpression`. It's pretty straightforward: it creates a temporary variable, initializes it with an `Uninitialized` instruction, then initializes the individual captured fields with the initializer list supplied in the AST.

When testing the case of a lambda with no captures, I noticed that we weren't handling initialization of empty structs with an initializer list correctly, so I fixed that along the way.

I was getting confused by the bad indentation for wrapped lines in
TranslatedInitialization.qll, so I fixed that up in a separate commit.
2019-03-22 15:17:27 -07:00
Dave Bartolomeo
b5a3edfdae C++: FunctionIR -> IRFunction 2019-03-12 11:28:22 -07:00
Robert Marsh
17ad124c9e C++: remove VariableAddress from points_to test 2019-03-07 13:14:56 -08:00
Robert Marsh
7e30ce0c09 C++: add phi node support to escape analysis 2019-03-07 13:14:56 -08:00
Robert Marsh
97c11a5222 C++: points-to for argument-returning calls 2019-03-07 13:14:55 -08:00
Robert Marsh
c70bd285de C++: assume arguments to virtual functions escape 2019-03-07 13:14:49 -08:00
Robert Marsh
2c94a8887d C++: test for virtual functions in escape analysis 2019-03-07 13:14:49 -08:00
Robert Marsh
6089172554 C++: escape analysis for this parameters 2019-03-07 13:14:49 -08:00
Robert Marsh
466e110338 C++: add new interprocedural escape analysis 2019-03-07 13:14:48 -08:00
Robert Marsh
bd39698528 C++: test changes for interproc escape analysis 2019-03-07 13:14:48 -08:00
Dave Bartolomeo
b40fd95b8e C++: Better tracking of SSA memory accesses
This change fixes a few key problems with the existing SSA implementations:

For unaliased SSA, we were incorrectly choosing to model a local variable that had accesses that did not cover the entire variable. This has been changed to ensure that all accesses to the variable are at offset zero and have the same type as the variable itself. This was only possible to fix now that every `MemoryOperand` has its own type.

For aliased SSA, we now correctly track the offset and size of each memory access using an interval of bit offsets covered by the access. The offset interval makes the overlap computation more straightforward. Again, this is only possible now that operands have types.
The `getXXXMemoryAccess` predicates are now driven by the `MemoryAccessKind` on the operands and results, instead of by specific opcodes.

This change does fix an existing false negative in the IR dataflow tests.

I added a few simple test cases to the SSA IR tests, covering the various kinds of overlap (MustExcactly, MustTotally, and MayPartially).

I added "PrintSSA.qll", which can dump the SSA memory accesses as part of an IR dump.
2019-02-13 10:44:39 -08:00
Dave Bartolomeo
aff2ea3316 C++: Handle pointer decay and inferred array sizes
For function parameters that are subject to "pointer decay", the database contains the type as originally declared (e.g. `T[]` instead of `T*`). The IR needs the actual type. Similarly, for variable declared as an array of unknown size, the actual size needs to be inferred from the initializer (e.g. `char a[] = "blah";` needs to have the type `char[5]`).

I've opened a ticket to have the extractor emit the actual type alongside the declared type, but for now, this workaround is enough to unblock progress for typical code.
2019-02-12 12:41:21 -08:00
Dave Bartolomeo
bd46c43067 C++: Add sanity test for missing operand type 2019-02-11 09:47:00 -08:00
Dave Bartolomeo
bda00bbff2 C++: Split out SSA IR tests
The IR tests were getting kind of unwieldy. We were using "ir.cpp" to contain test cases that covered both IR construction (every language construct imaginable) and SSA construction. We would then build and dump all three flavors of IR. For IR construction tests, examining the SSA dumps when you add a new test case is tedious.

To make this easier to manage, I've split the SSA-specific test cases out into a separate directory. "ir.cpp" should now contain only IR construction test cases, and "ssa.cpp" should contain only SSA construction test cases. We dump just the raw IR for "ir.cpp", and just the two SSA flavors for "ssa.cpp". We still run all three flavors of the IR sanity tests for "ir.cpp", though.

I also removed the "ssa_block_count.ql" test, which wasn't really adding any coverage, because any change to the block count would be reflected in the dump as well.
2019-02-08 15:28:06 -08:00
Dave Bartolomeo
1e7dcedcdf C++: Fix semantic merge conflict 2019-02-07 14:32:26 -08:00
Dave Bartolomeo
7b54db8ca9 C++: Fix getIdentityString for TemplateParameter 2019-02-07 14:26:00 -08:00
Dave Bartolomeo
bd4ecc3e91 C++: Declaration.getIdentityString and Type.getTypeIdentityString
This PR adds new predicates to `Declaration` and `Type` to get a fully-qualified canonical name for the element, suitable for debugging and dumps. It includes template parameters, cv qualifiers, function parameter and return types, and fully-qualified names for all symbols. These strings are too large to compute in productions queries, so they should be used only for dumps and debugging. Feel free to suggest better names for these predicates.

I've updated PrintAST and PrintIR to use these instead of `Function.getFullSignature()`. The biggest advantage of the new predicates is that they handle lambdas and local classes, which `getQualifiedName` and `getFullSignature` do not. This makes IR and AST dumps much more usable for real-world snapshots.

Along the way, I cleaned up some of our handling of `IntegralType` to use a single table for tracking the signed, unsigned, and canonical versions of each type. The canonical part is new, and was necessary for `getTypeIdentityString` so that `signed int` and `int` both appear as `int`.
2019-02-07 14:26:00 -08:00
Dave Bartolomeo
4c23ad100e C++: Rename a few IR APIs
There are a few IR APIs that we've found to be confusingly named. This PR renames them to be more consistent within the IR and with the AST API:

`Instruction.getFunction` -> `Instruction.getEnclosingFunction`: This was especially confusing when you'd call `FunctionAddressInstruction.getFunction` to get the function whose address was taken, and wound up with the enclosing function instead.

`Instruction.getXXXOperand` -> `Instruction.getXXX`. Now that `Operand` is an exposed type, we want a way to get a specific `Operand` of an `Instruction`, but more often we want to get the definition instruction of that operand. Now, the pattern is that `getXXXOperand` returns the `Operand`, and `getXXX` is equivalent to `getXXXOperand().getDefinitionInstruction()`.

`Operand.getInstruction` -> `Operand.getUseInstruction`: More consistent with the existing `Operand.getDefinitionInstruction` predicate.
2019-02-06 22:43:49 -08:00
Robert Marsh
5327ca7f77 Merge pull request #812 from jbj/ir-backedge
C++: IR back-edge detection based on TranslatedStmt
2019-01-31 11:28:21 -08:00
Jonas Jensen
ba8bf94d7b C++: Account for chi nodes in back-edge detection 2019-01-25 15:32:19 +01:00
Jonas Jensen
560dbdf984 C++: Test demonstrating chi node back edge bug
This test shows that the back-edge detection does not properly account
for chi nodes in the translation to aliased SSA.
2019-01-25 15:28:53 +01:00
Jonas Jensen
9963270d63 C++: Annotate back edges in IR debug output 2019-01-25 14:16:45 +01:00
Jonas Jensen
b40accee6f C++: sanity checks for back edges 2019-01-23 11:40:12 +01:00
Jonas Jensen
b2e5d235de C++: IR sanity queries for outgoing edges
These queries have no results on our test cases in the repo, but
`ambiguousSuccessors` has results on any large C++ code base, and
`unexplainedLoop` has results on Windows builds of ChakraCore.
2019-01-23 11:07:49 +01:00
Dave Bartolomeo
fda8605aae C++: One Unreached per function 2018-12-17 11:03:15 -08:00
Dave Bartolomeo
56bb9dcde0 C++: Remove infeasible edges to reachable blocks
The existing unreachable IR removal code only retargeted an infeasible edge to an `Unreached` instruction if the successor of the edge was an unreachable block. This is too conservative, because it doesn't remove an infeasible edge that targets a block that is still reachable via other paths. The trivial example of this is `do { } while (false);`, where the back edge is infeasible, but the body block is still reachable from the loop entry.

This change retargets all infeasible edges to `Unreached` instructions, regardless of the reachability of the successor block.
2018-12-14 12:13:22 -08:00
Dave Bartolomeo
4170d4fadd C++: Handle relational operators in constant analysis 2018-12-10 23:03:02 -08:00
Dave Bartolomeo
99d33f9623 C++: Remove unreachable IR
This change removes any IR instructions that can be statically proven unreachable. To detect unreachable IR, we first run a simple constant value analysis on the IR. Then, any `ConditionalBranch` with a constant condition has the appropriate edge marked as "infeasible". We define a class `ReachableBlock` as any `IRBlock` with a path from the entry block of the function. SSA construction has been modified to operate only on `ReachableBlock` and `ReachableInstruction`, which ensures that only reachable IR gets translated into SSA form. For any infeasible edge where its predecessor block is reachable, we replace the original target of the branch with an `Unreached` instruction, which lets us preserve the invariant that all `ConditionalBranch` instructions have both a true and a false edge, and allows guard inference to still work.

The changes to `SSAConstruction.qll` are not as scary as they look. They are almost entirely a mechanical replacement of `OldIR::IRBlock` with `OldBlock`, which is just an alias for `ReachableBlock`.

Note that the `constant_func.ql` test can determine that the two new test functions always return 0.

Removing unreachable code helps get rid of some common FPs in IR-based dataflow analysis, especially for constructs like `while(true)`.
2018-12-10 21:22:55 -08:00
Dave Bartolomeo
59fc77f066 C++: Simple constant analysis
This change moves the simple constant analysis that was used by the const_func test into a pyrameterized module for use on any stage of the IR. This will be used to detect unreachable code.
2018-12-10 21:22:54 -08:00
Dave Bartolomeo
6a11ef5c18 C++: Add a couple test cases for unreachable code in IR 2018-12-10 21:22:54 -08:00
Dave Bartolomeo
7eb47f3f82 C++: A few more IR dataflow tweaks
Made `Node::getType()`, `Node::asParameter()`, and `Node::asUninitialized()` operate directly on the IR. This actually fixed several diffs compared to the AST dataflow, because `getType()` wasn't holding for nodes that weren't `Exprs`.

Made `Uninitialized` a `VariableInstruction`. This makes it consistent with `InitializeParameter`.
2018-11-30 16:53:45 -08:00
Dave Bartolomeo
af443569d9 C++: Fix handling of accesses to escaped variables in Aliased SSA
This fixes a subtle bug in the construction of aliased SSA. `getResultMemoryAccess` was failing to return a `MemoryAccess` for a store to a variable whose address escaped. This is because no `VirtualIRVariable` was being created for such variables. The code was assuming that any access to such a variable would be via `UnknownMemoryAccess`. The result is that accesses to such variables were not being modeled in SSA at all.

Instead, the way to handle this is to have a `VariableMemoryAccess` even when the variable being accessed has escaped, and to have `VariableMemoryAccess::getVirtualVariable()` return the `UnknownVirtualVariable` for escaped variables. In the future, this will also let us be less conservative about inserting `Chi` nodes, because we'll be able to determine that there's an exact overlap between two accesses to the same escaped variable in some cases.
2018-11-30 12:15:19 -08:00
Dave Bartolomeo
7e6e6f00c1 C++: Fix IR for designated array initializers 2018-11-27 14:57:23 -08:00
Dave Bartolomeo
0a20f9ffbf C++: Print field names and element indices for aggregate literals in PrintAST 2018-11-27 13:26:18 -08:00
Dave Bartolomeo
2b9afe95e8 C++: Accept test output after rebase 2018-11-26 12:08:19 -08:00
Robert Marsh
799eb06eea C++: add AliasedDefinition for aliased SSA 2018-11-26 12:08:19 -08:00
Robert Marsh
3ee033d96e C++: IR sanity fixes for Chi nodes 2018-11-26 12:08:19 -08:00
Robert Marsh
b401cd97f2 C++: use UnmodeledDefinition in UnmodeledUse 2018-11-26 12:08:19 -08:00
Robert Marsh
927f935e62 C++: hook ChiInstructions into the operand graph 2018-11-26 12:08:19 -08:00
Robert Marsh
a33b59103a C++: insert Chi nodes in the IR successor relation
This commit adds Chi nodes to the successor relation and accounts for
them in the CFG, but does not add them to the SSA data graph. Chi nodes
are inserted for partial writes to any VirtualVariable, regardless of
whether the partial write reaches any uses.
2018-11-26 12:08:18 -08:00
Dave Bartolomeo
1fb36ff7e7 C++: Add conservative side effects for function calls 2018-11-26 12:08:18 -08:00
Aditya Sharad
c20b688a3f Merge master into next. 2018-11-23 16:36:31 +00:00
Jonas Jensen
da26b4f856 C++: Accept test changes for IR
This test was failing due to a semantic merge conflict between #509,
which added `UninitializedInstruction`, and #517, which added new test
code that would get `UninitializedInstruction`s in it after merging with #509.
2018-11-22 13:52:33 +01:00
Jonas Jensen
e062851709 Merge pull request #517 from dave-bartolomeo/dave/IRFilter
C++: Don't generate IR for functions with bad ASTs
2018-11-22 10:02:18 +01:00
Dave Bartolomeo
97fd7b46cc C++: Add tests for filtering bad ASTs 2018-11-21 16:39:08 -08:00