Skip to content

Commit f65d1e8

Browse files
authored
Merge pull request #21554 from github/copilot/make-go-use-ssa-library
Go: use shared SSA library (codeql.ssa.Ssa)
2 parents 2686026 + db5fac1 commit f65d1e8

41 files changed

Lines changed: 908 additions & 1195 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

go/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ dependencies:
1010
codeql/controlflow: ${workspace}
1111
codeql/dataflow: ${workspace}
1212
codeql/mad: ${workspace}
13+
codeql/ssa: ${workspace}
1314
codeql/threat-models: ${workspace}
1415
codeql/tutorial: ${workspace}
1516
codeql/util: ${workspace}

go/ql/lib/semmle/go/controlflow/BasicBlocks.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ private module Input implements BB::InputSig<Location> {
4242
predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
4343
}
4444

45-
private module BbImpl = BB::Make<Location, Input>;
45+
module Cfg = BB::Make<Location, Input>;
4646

47-
class BasicBlock = BbImpl::BasicBlock;
47+
class BasicBlock = Cfg::BasicBlock;
4848

49-
class EntryBasicBlock = BbImpl::EntryBasicBlock;
49+
class EntryBasicBlock = Cfg::EntryBasicBlock;
5050

5151
cached
5252
private predicate reachableBB(BasicBlock bb) {

go/ql/lib/semmle/go/dataflow/SSA.qll

Lines changed: 24 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -63,33 +63,25 @@ private predicate unresolvedIdentifier(Ident id, string name) {
6363
/**
6464
* An SSA variable.
6565
*/
66-
class SsaVariable extends TSsaDefinition {
67-
/** Gets the source variable corresponding to this SSA variable. */
68-
SsaSourceVariable getSourceVariable() { result = this.(SsaDefinition).getSourceVariable() }
69-
66+
class SsaVariable extends Definition {
7067
/** Gets the (unique) definition of this SSA variable. */
7168
SsaDefinition getDefinition() { result = this }
7269

7370
/** Gets the type of this SSA variable. */
7471
Type getType() { result = this.getSourceVariable().getType() }
7572

7673
/** Gets a use in basic block `bb` that refers to this SSA variable. */
77-
IR::Instruction getAUseIn(ReachableBasicBlock bb) {
74+
IR::Instruction getAUseIn(BasicBlock bb) {
7875
exists(int i, SsaSourceVariable v | v = this.getSourceVariable() |
7976
result = bb.getNode(i) and
80-
this = getDefinition(bb, i, v)
77+
ssaDefReachesRead(v, this, bb, i) and
78+
useAt(bb, i, v)
8179
)
8280
}
8381

8482
/** Gets a use that refers to this SSA variable. */
8583
IR::Instruction getAUse() { result = this.getAUseIn(_) }
8684

87-
/** Gets a textual representation of this element. */
88-
string toString() { result = this.getDefinition().prettyPrintRef() }
89-
90-
/** Gets the location of this SSA variable. */
91-
Location getLocation() { result = this.getDefinition().getLocation() }
92-
9385
/**
9486
* DEPRECATED: Use `getLocation()` instead.
9587
*
@@ -109,50 +101,20 @@ class SsaVariable extends TSsaDefinition {
109101
/**
110102
* An SSA definition.
111103
*/
112-
class SsaDefinition extends TSsaDefinition {
104+
class SsaDefinition extends Definition {
113105
/** Gets the SSA variable defined by this definition. */
114106
SsaVariable getVariable() { result = this }
115107

116-
/** Gets the source variable defined by this definition. */
117-
abstract SsaSourceVariable getSourceVariable();
118-
119-
/**
120-
* Gets the basic block to which this definition belongs.
121-
*/
122-
abstract ReachableBasicBlock getBasicBlock();
123-
124-
/**
125-
* INTERNAL: Use `getBasicBlock()` and `getSourceVariable()` instead.
126-
*
127-
* Holds if this is a definition of source variable `v` at index `idx` in basic block `bb`.
128-
*
129-
* Phi nodes are considered to be at index `-1`, all other definitions at the index of
130-
* the control flow node they correspond to.
131-
*/
132-
abstract predicate definesAt(ReachableBasicBlock bb, int idx, SsaSourceVariable v);
133-
134-
/**
135-
* INTERNAL: Use `toString()` instead.
136-
*
137-
* Gets a pretty-printed representation of this SSA definition.
138-
*/
139-
abstract string prettyPrintDef();
108+
/** Gets the innermost function or file to which this SSA definition belongs. */
109+
ControlFlow::Root getRoot() { result = this.getBasicBlock().getScope() }
140110

141111
/**
142112
* INTERNAL: Do not use.
143113
*
144-
* Gets a pretty-printed representation of a reference to this SSA definition.
114+
* Gets a short string identifying the kind of this SSA definition,
115+
* used in reference formatting (e.g., `"def"`, `"capture"`, `"phi"`).
145116
*/
146-
abstract string prettyPrintRef();
147-
148-
/** Gets the innermost function or file to which this SSA definition belongs. */
149-
ControlFlow::Root getRoot() { result = this.getBasicBlock().getScope() }
150-
151-
/** Gets a textual representation of this element. */
152-
string toString() { result = this.prettyPrintDef() }
153-
154-
/** Gets the source location for this element. */
155-
abstract Location getLocation();
117+
string getKind() { none() }
156118

157119
/**
158120
* DEPRECATED: Use `getLocation()` instead.
@@ -180,32 +142,23 @@ class SsaDefinition extends TSsaDefinition {
180142
/**
181143
* An SSA definition that corresponds to an explicit assignment or other variable definition.
182144
*/
183-
class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
145+
class SsaExplicitDefinition extends SsaDefinition, WriteDefinition {
146+
SsaExplicitDefinition() {
147+
exists(BasicBlock bb, int i, SsaSourceVariable v |
148+
this.definesAt(v, bb, i) and
149+
defAt(bb, i, v)
150+
)
151+
}
152+
184153
/** Gets the instruction where the definition happens. */
185154
IR::Instruction getInstruction() {
186-
exists(BasicBlock bb, int i | this = TExplicitDef(bb, i, _) | result = bb.getNode(i))
155+
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i))
187156
}
188157

189158
/** Gets the right-hand side of the definition. */
190159
IR::Instruction getRhs() { this.getInstruction().writes(_, result) }
191160

192-
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
193-
this = TExplicitDef(bb, i, v)
194-
}
195-
196-
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
197-
198-
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, result) }
199-
200-
override string prettyPrintRef() {
201-
exists(Location loc | loc = this.getLocation() |
202-
result = "def@" + loc.getStartLine() + ":" + loc.getStartColumn()
203-
)
204-
}
205-
206-
override string prettyPrintDef() { result = "definition of " + this.getSourceVariable() }
207-
208-
override Location getLocation() { result = this.getInstruction().getLocation() }
161+
override string getKind() { result = "def" }
209162
}
210163

211164
/** Provides a helper predicate for working with explicit SSA definitions. */
@@ -219,22 +172,7 @@ module SsaExplicitDefinition {
219172
/**
220173
* An SSA definition that does not correspond to an explicit variable definition.
221174
*/
222-
abstract class SsaImplicitDefinition extends SsaDefinition {
223-
/**
224-
* INTERNAL: Do not use.
225-
*
226-
* Gets the definition kind to include in `prettyPrintRef`.
227-
*/
228-
abstract string getKind();
229-
230-
override string prettyPrintRef() {
231-
exists(Location loc | loc = this.getLocation() |
232-
result = this.getKind() + "@" + loc.getStartLine() + ":" + loc.getStartColumn()
233-
)
234-
}
235-
236-
override Location getLocation() { result = this.getBasicBlock().getLocation() }
237-
}
175+
abstract class SsaImplicitDefinition extends SsaDefinition { }
238176

239177
/**
240178
* An SSA definition representing the capturing of an SSA-convertible variable
@@ -243,24 +181,8 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
243181
* Capturing definitions appear at the beginning of such functions, as well as
244182
* at any function call that may affect the value of the variable.
245183
*/
246-
class SsaVariableCapture extends SsaImplicitDefinition, TCapture {
247-
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
248-
this = TCapture(bb, i, v)
249-
}
250-
251-
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
252-
253-
override SsaSourceVariable getSourceVariable() { this.definesAt(_, _, result) }
254-
184+
class SsaVariableCapture extends SsaImplicitDefinition, UncertainWriteDefinition {
255185
override string getKind() { result = "capture" }
256-
257-
override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }
258-
259-
override Location getLocation() {
260-
exists(ReachableBasicBlock bb, int i | this.definesAt(bb, i, _) |
261-
result = bb.getNode(i).getLocation()
262-
)
263-
}
264186
}
265187

266188
/**
@@ -272,39 +194,17 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
272194
* Gets an input of this pseudo-definition.
273195
*/
274196
abstract SsaVariable getAnInput();
275-
276-
/**
277-
* Gets a textual representation of the inputs of this pseudo-definition
278-
* in lexicographical order.
279-
*/
280-
string ppInputs() { result = concat(this.getAnInput().getDefinition().prettyPrintRef(), ", ") }
281197
}
282198

283199
/**
284200
* An SSA phi node, that is, a pseudo-definition for a variable at a point
285201
* in the flow graph where otherwise two or more definitions for the variable
286202
* would be visible.
287203
*/
288-
class SsaPhiNode extends SsaPseudoDefinition, TPhi {
289-
override SsaVariable getAnInput() {
290-
result = getDefReachingEndOf(this.getBasicBlock().getAPredecessor(_), this.getSourceVariable())
291-
}
292-
293-
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
294-
bb = this.getBasicBlock() and v = this.getSourceVariable() and i = -1
295-
}
296-
297-
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
298-
299-
override SsaSourceVariable getSourceVariable() { this = TPhi(_, result) }
204+
class SsaPhiNode extends SsaPseudoDefinition, PhiNode {
205+
override SsaVariable getAnInput() { phiHasInputFromBlock(this, result, _) }
300206

301207
override string getKind() { result = "phi" }
302-
303-
override string prettyPrintDef() {
304-
result = this.getSourceVariable() + " = phi(" + this.ppInputs() + ")"
305-
}
306-
307-
override Location getLocation() { result = this.getBasicBlock().getLocation() }
308208
}
309209

310210
/**

0 commit comments

Comments
 (0)