Commit Graph

368 Commits

Author SHA1 Message Date
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
Dave Bartolomeo
3715215b3f C++: Add IR support for ConditionalDeclExpr
Also fixes several places in the library that weren't handling `ConditionalDeclExpr`  correctly.
2018-11-21 00:14:44 -08:00
Dave Bartolomeo
07f9fe6ee4 C++: Add Uninitialized instruction for list-initialized variables
This commit inserts an `Uninitialized` instruction to "initialize" a local variable when that variable is initialized with an initializer list. This ensures that there is always a definition of the whole variable before any read or write to part of that variable.

This change appears in a different form in @rdmarsh2's Chi node PR, but I needed to refactor the initialization code anyway to handle ConditionDeclExpr.
2018-11-20 16:12:44 -08:00
Aditya Sharad
553c2f5d34 Merge master into next.
As of 2846d80f1c.
2018-11-06 11:52:51 +00:00
Ian Lynagh
01d27d331e C++: Accept test changes 2018-10-26 11:07:18 +01:00
Dave Bartolomeo
f278f4fa47 C++: Operands as IPA types
@rdmarsh2 has been working on various queries and libraries on top of the IR, and has pointed out that having to always refer to an operand of an instruction by the pair of (instruction, operandTag) makes using the IR a bit clunky. This PR adds a new `Operand` IPA type that represents an operand of an instruction. `OperandTag` still exists, but is now an internal type used only in the IR implementation.
2018-10-23 14:58:44 -07:00
Ian Lynagh
894a37ccda C++: Accept test changes 2018-10-18 12:36:42 +01:00
Dave Bartolomeo
aa267c8302 C++: Force LF for .c,.cpp,.h,.hpp 2018-09-23 16:23:52 -07:00
Jonas Jensen
e2a17e9740 Merge remote-tracking branch 'upstream/rc/1.18' into mergeback-20180921_104253 2018-09-21 10:45:54 +02:00
Dave Bartolomeo
43f0289f0f C++: Remove Phi instructions from previous IR generations
It turns out that when building aliased SSA IR, we were still keeping around the Phi instructions from unaliased SSA IR. These leftover instructions didn't show up in dumps because they were not assigned to a block. However, when dumping additional instruction properties, they would show up as a top-level node in the dump, without a label.
2018-09-18 11:28:09 -07:00
Jonas Jensen
df948ecbbc C++: IR: designated initializer test 2018-09-11 19:43:02 +02:00
Dave Bartolomeo
4086a8909b C++: Fix a couple IR-related tests to handle new directory tree
Also moved those tests under the IR test directory, so I'm less likely to forget them next time.
2018-09-04 09:05:33 -07:00
Dave Bartolomeo
fce7a5fccb C++: Final IR reshuffle
Moved IR flavors into "implementation", with internal files under "implementation/internal". Made `IRBlockConstruction` just a nested module of `IRConstruction`/`SSAConstruction`, so it gets picked up from the `Construction` parameter of the `IR` module, rather than being picked up just from being in the same directory as `IRBlock`.
2018-09-04 09:05:27 -07:00