Commit Graph

359 Commits

Author SHA1 Message Date
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
Dave Bartolomeo
aa4436fa22 C++: More IR reshuffling
Remove redundant "_ir" suffix.
Move non-user-importable modules into "implementation" directory.
2018-09-04 09:05:21 -07:00
Dave Bartolomeo
97cfbd9488 C++: "IR" means "Aliased SSA IR"
This change makes the public IR.qll module resolve to the flavor of the IR that we want queries to use. Today, this is the aliased SSA flavor of the IR. Should we add additional IR iterations in the future, we'll update IR.qll to resolve to whichever one we consider the default.

I moved the PrintIR.ql and IRSanity.ql queries into the internal directories of the corresponding flavors. There's still a PrintIR.ql and an IRSanity.ql in the public IR directory, which use the same IR flavor as the public IR.qll.
2018-09-04 09:05:15 -07:00
Dave Bartolomeo
aacee8fecf C++: Reshuffle IR files into a consistent directory structure
There are no real code changes here, other than to fix up `import`s. All tests still hae the same output, as expected.

A future commit will hide the IR flavors other than the one we want queries to use directly.
2018-09-04 09:05:03 -07:00
Dave Bartolomeo
b44c2c72a6 C++: Invoke -> Call
Now that opcodes are in their own module that isn't imported into the global namespace, `Opcode::Call` no longer conflicts with `Call` from the ASTs. I've renamed `Opcode::Invoke` to `Opcode::Call`.
2018-08-27 09:22:01 -07:00
Pavel Avgustinov
d0497a5cff Merge pull request #106 from dave-bartolomeo/dave/LF
Force LF line endings for .ql, .qll, .qlref, and .dbscheme
2018-08-27 10:04:53 +01:00
Dave Bartolomeo
d920fc7d94 Force LF line endings for .ql, .qll, and .qlref files 2018-08-24 11:58:58 -07:00
Nick Rolfe
04385a83ba C++: fix tests: frontend no longer optimises dynamic_cast to base type 2018-08-24 18:41:37 +01:00
Dave Bartolomeo
c4d6e1b01c C++: Fix wobble in PrintAST test
PrintAST.ql orders the functions by location, then in lexicographical order of the function signature. This is supposed to ensure a stable ordering, but functions without a location were not getting assigned an order at all.
2018-08-24 08:36:30 -07:00
Dave Bartolomeo
72e72357c2 C++: Use glval<Unknown> as type of call target
Also shared some code between `TranslatedFunctionCall` and `TranslatedAllocatorCall`, and fixed dumps of glval<Unknown> to not print the size.
2018-08-23 09:43:58 -07:00