@eagleoutice/flowr 2.9.7 → 2.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -21
- package/abstract-interpretation/absint-visitor.d.ts +5 -4
- package/abstract-interpretation/absint-visitor.js +12 -11
- package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
- package/control-flow/basic-cfg-guided-visitor.js +7 -6
- package/control-flow/cfg-dead-code.js +12 -9
- package/control-flow/cfg-properties.d.ts +2 -2
- package/control-flow/cfg-properties.js +3 -2
- package/control-flow/cfg-to-basic-blocks.js +9 -12
- package/control-flow/control-flow-graph.d.ts +382 -78
- package/control-flow/control-flow-graph.js +591 -106
- package/control-flow/dfg-cfg-guided-visitor.d.ts +4 -4
- package/control-flow/dfg-cfg-guided-visitor.js +3 -3
- package/control-flow/diff-cfg.js +35 -29
- package/control-flow/extract-cfg.d.ts +3 -3
- package/control-flow/extract-cfg.js +145 -125
- package/control-flow/happens-before.js +2 -1
- package/control-flow/semantic-cfg-guided-visitor.js +2 -1
- package/control-flow/simple-visitor.js +8 -6
- package/control-flow/syntax-cfg-guided-visitor.js +2 -1
- package/control-flow/useless-loop.js +2 -1
- package/documentation/wiki-cfg.js +21 -9
- package/documentation/wiki-mk/doc-maker.js +1 -1
- package/package.json +1 -1
- package/project/context/flowr-file.d.ts +5 -0
- package/project/context/flowr-file.js +7 -0
- package/project/plugins/file-plugins/files/flowr-description-file.d.ts +1 -0
- package/project/plugins/file-plugins/files/flowr-description-file.js +5 -0
- package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +4 -0
- package/project/plugins/file-plugins/files/flowr-namespace-file.js +8 -0
- package/project/plugins/file-plugins/files/flowr-news-file.d.ts +4 -0
- package/project/plugins/file-plugins/files/flowr-news-file.js +8 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.js +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +2 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +19 -19
- package/search/search-executor/search-generators.js +2 -2
- package/util/assert.d.ts +3 -3
- package/util/mermaid/cfg.d.ts +1 -7
- package/util/mermaid/cfg.js +37 -44
- package/util/version.js +1 -1
|
@@ -7,7 +7,6 @@ exports.getCallsInCfg = getCallsInCfg;
|
|
|
7
7
|
exports.cfg2quads = cfg2quads;
|
|
8
8
|
const quads_1 = require("../util/quads");
|
|
9
9
|
const fold_1 = require("../r-bridge/lang-4.x/ast/model/processing/fold");
|
|
10
|
-
const convert_values_1 = require("../r-bridge/lang-4.x/convert-values");
|
|
11
10
|
const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
12
11
|
const linker_1 = require("../dataflow/internal/linker");
|
|
13
12
|
const vertex_1 = require("../dataflow/graph/vertex");
|
|
@@ -102,35 +101,57 @@ function cfgFoldProject(proj, folds) {
|
|
|
102
101
|
else if (proj.files.length === 1) {
|
|
103
102
|
return (0, fold_1.foldAst)(proj.files[0].root, folds);
|
|
104
103
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
/* for many files, it is too expensive to keep all asts at once, hence we create and merge them incrementally */
|
|
105
|
+
let exitPoints;
|
|
106
|
+
let finalGraph;
|
|
107
|
+
let firstEntryPoints;
|
|
108
|
+
let breaks;
|
|
109
|
+
let nexts;
|
|
110
|
+
let returns;
|
|
111
|
+
{
|
|
112
|
+
const firstInfo = (0, fold_1.foldAst)(proj.files[0].root, folds);
|
|
113
|
+
exitPoints = firstInfo.exitPoints;
|
|
114
|
+
finalGraph = firstInfo.graph;
|
|
115
|
+
firstEntryPoints = firstInfo.entryPoints;
|
|
116
|
+
breaks = firstInfo.breaks;
|
|
117
|
+
nexts = firstInfo.nexts;
|
|
118
|
+
returns = firstInfo.returns;
|
|
119
|
+
}
|
|
120
|
+
for (let i = 1; i < proj.files.length; i++) {
|
|
121
|
+
const nextInfo = (0, fold_1.foldAst)(proj.files[i].root, folds);
|
|
122
|
+
finalGraph.mergeWith(nextInfo.graph);
|
|
123
|
+
for (const exitPoint of exitPoints) {
|
|
124
|
+
for (const entryPoint of nextInfo.entryPoints) {
|
|
125
|
+
finalGraph.addEdge(entryPoint, exitPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
112
126
|
}
|
|
113
127
|
}
|
|
128
|
+
exitPoints = nextInfo.exitPoints;
|
|
129
|
+
breaks.push(...nextInfo.breaks);
|
|
130
|
+
nexts.push(...nextInfo.nexts);
|
|
131
|
+
returns.push(...nextInfo.returns);
|
|
114
132
|
}
|
|
115
133
|
return {
|
|
116
|
-
breaks
|
|
117
|
-
nexts
|
|
118
|
-
returns
|
|
119
|
-
exitPoints
|
|
120
|
-
entryPoints:
|
|
134
|
+
breaks,
|
|
135
|
+
nexts,
|
|
136
|
+
returns,
|
|
137
|
+
exitPoints,
|
|
138
|
+
entryPoints: firstEntryPoints,
|
|
121
139
|
graph: finalGraph
|
|
122
140
|
};
|
|
123
141
|
}
|
|
124
142
|
function cfgLeaf(type) {
|
|
125
|
-
return ({ info: { id } }) => {
|
|
126
|
-
return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex(
|
|
143
|
+
return type === control_flow_graph_1.CfgVertexType.Expression ? ({ info: { id } }) => {
|
|
144
|
+
return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex(control_flow_graph_1.CfgVertex.makeExpression(id)), breaks: [], nexts: [], returns: [], exitPoints: [id], entryPoints: [id] };
|
|
145
|
+
} : ({ info: { id } }) => {
|
|
146
|
+
return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex(control_flow_graph_1.CfgVertex.makeStatement(id)), breaks: [], nexts: [], returns: [], exitPoints: [id], entryPoints: [id] };
|
|
127
147
|
};
|
|
128
148
|
}
|
|
149
|
+
const cfgLeafStatement = cfgLeaf(control_flow_graph_1.CfgVertexType.Statement);
|
|
129
150
|
function cfgBreak(leaf) {
|
|
130
|
-
return { ...
|
|
151
|
+
return { ...cfgLeafStatement(leaf), breaks: [leaf.info.id], exitPoints: [] };
|
|
131
152
|
}
|
|
132
153
|
function cfgNext(leaf) {
|
|
133
|
-
return { ...
|
|
154
|
+
return { ...cfgLeafStatement(leaf), nexts: [leaf.info.id], exitPoints: [] };
|
|
134
155
|
}
|
|
135
156
|
function cfgIgnore(_leaf) {
|
|
136
157
|
return { graph: new control_flow_graph_1.ControlFlowGraph(), breaks: [], nexts: [], returns: [], exitPoints: [], entryPoints: [] };
|
|
@@ -141,32 +162,34 @@ function identifyMayStatementType(node) {
|
|
|
141
162
|
function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
142
163
|
const ifId = ifNode.info.id;
|
|
143
164
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
144
|
-
graph.addVertex(
|
|
145
|
-
graph.addVertex(
|
|
165
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(ifId, identifyMayStatementType(ifNode), { mid: condition.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(ifId)] }));
|
|
166
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(ifId));
|
|
146
167
|
graph.mergeWith(condition.graph);
|
|
147
168
|
graph.mergeWith(then.graph);
|
|
148
169
|
if (otherwise) {
|
|
149
170
|
graph.mergeWith(otherwise.graph);
|
|
150
171
|
}
|
|
172
|
+
const cdTrue = control_flow_graph_1.CfgEdge.makeCdTrue(ifId);
|
|
173
|
+
const cdFalse = control_flow_graph_1.CfgEdge.makeCdFalse(ifId);
|
|
151
174
|
for (const e of condition.exitPoints) {
|
|
152
175
|
for (const entryPoint of then.entryPoints) {
|
|
153
|
-
graph.addEdge(entryPoint, e,
|
|
176
|
+
graph.addEdge(entryPoint, e, cdTrue);
|
|
154
177
|
}
|
|
155
178
|
for (const entryPoint of otherwise?.entryPoints ?? []) {
|
|
156
|
-
graph.addEdge(entryPoint, e,
|
|
179
|
+
graph.addEdge(entryPoint, e, cdFalse);
|
|
157
180
|
}
|
|
158
181
|
}
|
|
159
182
|
for (const entryPoint of condition.entryPoints) {
|
|
160
|
-
graph.addEdge(entryPoint, ifId,
|
|
183
|
+
graph.addEdge(entryPoint, ifId, control_flow_graph_1.CfgEdge.makeFd());
|
|
161
184
|
}
|
|
162
185
|
for (const exits of [then.exitPoints, otherwise?.exitPoints ?? []]) {
|
|
163
186
|
for (const exit of exits) {
|
|
164
|
-
graph.addEdge(ifId
|
|
187
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(ifId), exit, control_flow_graph_1.CfgEdge.makeFd());
|
|
165
188
|
}
|
|
166
189
|
}
|
|
167
190
|
if (!otherwise) {
|
|
168
191
|
for (const e of condition.exitPoints) {
|
|
169
|
-
graph.addEdge(ifId
|
|
192
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(ifId), e, control_flow_graph_1.CfgEdge.makeCdFalse(ifId));
|
|
170
193
|
}
|
|
171
194
|
}
|
|
172
195
|
return {
|
|
@@ -174,107 +197,100 @@ function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
|
174
197
|
breaks: then.breaks.concat(otherwise?.breaks ?? []),
|
|
175
198
|
nexts: then.nexts.concat(otherwise?.nexts ?? []),
|
|
176
199
|
returns: then.returns.concat(otherwise?.returns ?? []),
|
|
177
|
-
exitPoints: [ifId
|
|
200
|
+
exitPoints: [control_flow_graph_1.CfgVertex.toExitId(ifId)],
|
|
178
201
|
entryPoints: [ifId]
|
|
179
202
|
};
|
|
180
203
|
}
|
|
181
204
|
function cfgRepeat(repeat, body) {
|
|
182
205
|
const graph = body.graph;
|
|
183
|
-
|
|
184
|
-
graph.addVertex(
|
|
206
|
+
const rid = repeat.info.id;
|
|
207
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(rid, identifyMayStatementType(repeat), { end: [control_flow_graph_1.CfgVertex.toExitId(rid)] }));
|
|
208
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(rid));
|
|
185
209
|
for (const entryPoint of body.entryPoints) {
|
|
186
|
-
graph.addEdge(entryPoint,
|
|
210
|
+
graph.addEdge(entryPoint, rid, control_flow_graph_1.CfgEdge.makeFd());
|
|
187
211
|
}
|
|
188
212
|
// loops automatically
|
|
189
213
|
for (const nexts of [body.nexts, body.exitPoints]) {
|
|
190
214
|
for (const next of nexts) {
|
|
191
|
-
graph.addEdge(
|
|
215
|
+
graph.addEdge(rid, next, control_flow_graph_1.CfgEdge.makeFd());
|
|
192
216
|
}
|
|
193
217
|
}
|
|
194
218
|
for (const breakPoint of body.breaks) {
|
|
195
|
-
graph.addEdge(
|
|
219
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(rid), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
196
220
|
}
|
|
197
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [
|
|
221
|
+
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [control_flow_graph_1.CfgVertex.toExitId(rid)], entryPoints: [rid] };
|
|
198
222
|
}
|
|
199
223
|
function cfgWhile(whileLoop, condition, body) {
|
|
200
224
|
const whileId = whileLoop.info.id;
|
|
201
225
|
const graph = condition.graph;
|
|
202
|
-
graph.addVertex(
|
|
203
|
-
graph.addVertex(
|
|
226
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(whileId, identifyMayStatementType(whileLoop), { mid: condition.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(whileId)] }));
|
|
227
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(whileId));
|
|
204
228
|
graph.mergeWith(body.graph);
|
|
205
229
|
for (const entry of condition.entryPoints) {
|
|
206
|
-
graph.addEdge(entry, whileId,
|
|
230
|
+
graph.addEdge(entry, whileId, control_flow_graph_1.CfgEdge.makeFd());
|
|
207
231
|
}
|
|
208
232
|
for (const e of condition.exitPoints) {
|
|
209
233
|
for (const entry of body.entryPoints) {
|
|
210
|
-
graph.addEdge(entry, e,
|
|
234
|
+
graph.addEdge(entry, e, control_flow_graph_1.CfgEdge.makeCdTrue(whileId));
|
|
211
235
|
}
|
|
212
236
|
}
|
|
213
237
|
for (const nexts of [body.nexts, body.exitPoints]) {
|
|
214
238
|
for (const next of nexts) {
|
|
215
|
-
graph.addEdge(whileId, next,
|
|
239
|
+
graph.addEdge(whileId, next, control_flow_graph_1.CfgEdge.makeFd());
|
|
216
240
|
}
|
|
217
241
|
}
|
|
218
242
|
for (const breakPoint of body.breaks) {
|
|
219
|
-
graph.addEdge(whileId
|
|
243
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(whileId), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
220
244
|
}
|
|
221
245
|
// while can break on the condition as well
|
|
222
246
|
for (const e of condition.exitPoints) {
|
|
223
|
-
graph.addEdge(whileId
|
|
224
|
-
label: 1 /* CfgEdgeType.Cd */,
|
|
225
|
-
when: convert_values_1.RFalse,
|
|
226
|
-
caused: whileId
|
|
227
|
-
});
|
|
247
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(whileId), e, control_flow_graph_1.CfgEdge.makeCdFalse(whileId));
|
|
228
248
|
}
|
|
229
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [whileId
|
|
249
|
+
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [control_flow_graph_1.CfgVertex.toExitId(whileId)], entryPoints: [whileId] };
|
|
230
250
|
}
|
|
231
251
|
function cfgFor(forLoop, variable, vector, body) {
|
|
232
252
|
const forLoopId = forLoop.info.id;
|
|
233
253
|
const graph = variable.graph;
|
|
234
|
-
graph.addVertex(
|
|
254
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(forLoopId, identifyMayStatementType(forLoop), { mid: variable.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(forLoopId)] }));
|
|
235
255
|
graph.mergeWith(vector.graph);
|
|
236
256
|
graph.mergeWith(body.graph);
|
|
237
257
|
for (const entry of vector.entryPoints) {
|
|
238
|
-
graph.addEdge(entry, forLoopId,
|
|
258
|
+
graph.addEdge(entry, forLoopId, control_flow_graph_1.CfgEdge.makeFd());
|
|
239
259
|
}
|
|
240
260
|
for (const exit of vector.exitPoints) {
|
|
241
261
|
for (const entry of variable.entryPoints) {
|
|
242
|
-
graph.addEdge(entry, exit,
|
|
262
|
+
graph.addEdge(entry, exit, control_flow_graph_1.CfgEdge.makeFd());
|
|
243
263
|
}
|
|
244
264
|
}
|
|
245
265
|
for (const e of variable.exitPoints) {
|
|
246
266
|
for (const entry of body.entryPoints) {
|
|
247
|
-
graph.addEdge(entry, e,
|
|
267
|
+
graph.addEdge(entry, e, control_flow_graph_1.CfgEdge.makeCdTrue(forLoopId));
|
|
248
268
|
}
|
|
249
269
|
}
|
|
250
270
|
for (const points of [body.nexts, body.exitPoints]) {
|
|
251
271
|
for (const next of points) {
|
|
252
|
-
graph.addEdge(forLoopId, next,
|
|
272
|
+
graph.addEdge(forLoopId, next, control_flow_graph_1.CfgEdge.makeFd());
|
|
253
273
|
}
|
|
254
274
|
}
|
|
255
275
|
for (const breakPoint of body.breaks) {
|
|
256
|
-
graph.addEdge(forLoopId
|
|
276
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
257
277
|
}
|
|
258
278
|
const isNotEndless = body.exitPoints.length > 0 || body.breaks.length > 0;
|
|
259
279
|
if (isNotEndless) {
|
|
260
|
-
graph.addVertex(
|
|
261
|
-
id: forLoopId + '-exit',
|
|
262
|
-
type: control_flow_graph_1.CfgVertexType.EndMarker,
|
|
263
|
-
root: forLoopId
|
|
264
|
-
});
|
|
280
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(forLoopId));
|
|
265
281
|
for (const e of variable.exitPoints) {
|
|
266
|
-
graph.addEdge(forLoopId
|
|
282
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), e, control_flow_graph_1.CfgEdge.makeCdFalse(forLoopId));
|
|
267
283
|
}
|
|
268
284
|
}
|
|
269
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [forLoopId
|
|
285
|
+
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [control_flow_graph_1.CfgVertex.toExitId(forLoopId)] : [], entryPoints: [forLoopId] };
|
|
270
286
|
}
|
|
271
287
|
function cfgFunctionDefinition(fn, params, body) {
|
|
272
288
|
const fnId = fn.info.id;
|
|
273
289
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
274
290
|
let paramExits = params.flatMap(e => e.exitPoints);
|
|
275
|
-
const children = [...paramExits, fnId
|
|
276
|
-
graph.addVertex(
|
|
277
|
-
graph.addVertex(
|
|
291
|
+
const children = [...paramExits, control_flow_graph_1.CfgVertex.toExitId(fnId)];
|
|
292
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(fnId), false);
|
|
293
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(fnId, identifyMayStatementType(fn), { children, mid: paramExits, end: [control_flow_graph_1.CfgVertex.toExitId(fnId)] }));
|
|
278
294
|
graph.mergeWith(body.graph, true);
|
|
279
295
|
for (const r of body.graph.rootIds()) {
|
|
280
296
|
children.push(r);
|
|
@@ -285,7 +301,7 @@ function cfgFunctionDefinition(fn, params, body) {
|
|
|
285
301
|
children.push(r);
|
|
286
302
|
}
|
|
287
303
|
for (const entry of param.entryPoints) {
|
|
288
|
-
graph.addEdge(entry, fnId,
|
|
304
|
+
graph.addEdge(entry, fnId, control_flow_graph_1.CfgEdge.makeFd());
|
|
289
305
|
}
|
|
290
306
|
}
|
|
291
307
|
if (paramExits.length === 0) {
|
|
@@ -293,16 +309,16 @@ function cfgFunctionDefinition(fn, params, body) {
|
|
|
293
309
|
}
|
|
294
310
|
for (const e of paramExits) {
|
|
295
311
|
for (const entry of body.entryPoints) {
|
|
296
|
-
graph.addEdge(entry, e,
|
|
312
|
+
graph.addEdge(entry, e, control_flow_graph_1.CfgEdge.makeFd());
|
|
297
313
|
}
|
|
298
314
|
}
|
|
299
315
|
// breaks and nexts should be illegal but safe is safe, I guess
|
|
300
316
|
for (const next of body.returns.concat(body.breaks, body.nexts, body.exitPoints)) {
|
|
301
|
-
graph.addEdge(fnId
|
|
317
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(fnId), next, control_flow_graph_1.CfgEdge.makeFd());
|
|
302
318
|
}
|
|
303
319
|
return { graph: graph, breaks: [], nexts: [], returns: [], exitPoints: [fnId], entryPoints: [fnId] };
|
|
304
320
|
}
|
|
305
|
-
function cfgFunctionCall(call, name, args
|
|
321
|
+
function cfgFunctionCall(call, name, args) {
|
|
306
322
|
if (call.named && call.functionName.content === 'ifelse') {
|
|
307
323
|
// special built-in handling for ifelse as it is an expression that does not short-circuit
|
|
308
324
|
return cfgIfThenElse(call, args[0] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[0], args[1] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[1], args[2] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[2]);
|
|
@@ -314,14 +330,14 @@ function cfgFunctionCall(call, name, args, exit = 'exit') {
|
|
|
314
330
|
breaks: Array.from(name.breaks),
|
|
315
331
|
nexts: Array.from(name.nexts),
|
|
316
332
|
returns: Array.from(name.returns),
|
|
317
|
-
exitPoints: [callId
|
|
333
|
+
exitPoints: [control_flow_graph_1.CfgVertex.toExitId(callId)],
|
|
318
334
|
entryPoints: [callId]
|
|
319
335
|
};
|
|
320
|
-
graph.addVertex(
|
|
336
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(callId, identifyMayStatementType(call), { mid: name.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(callId)] }));
|
|
321
337
|
for (const entryPoint of name.entryPoints) {
|
|
322
|
-
graph.addEdge(entryPoint, callId,
|
|
338
|
+
graph.addEdge(entryPoint, callId, control_flow_graph_1.CfgEdge.makeFd());
|
|
323
339
|
}
|
|
324
|
-
graph.addVertex(
|
|
340
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(callId));
|
|
325
341
|
let lastArgExits = name.exitPoints;
|
|
326
342
|
for (const arg of args) {
|
|
327
343
|
if (arg === r_function_call_1.EmptyArgument) {
|
|
@@ -333,22 +349,22 @@ function cfgFunctionCall(call, name, args, exit = 'exit') {
|
|
|
333
349
|
info.returns = info.returns.concat(arg.returns);
|
|
334
350
|
for (const entry of arg.entryPoints) {
|
|
335
351
|
for (const exit of lastArgExits) {
|
|
336
|
-
graph.addEdge(entry, exit,
|
|
352
|
+
graph.addEdge(entry, exit, control_flow_graph_1.CfgEdge.makeFd());
|
|
337
353
|
}
|
|
338
354
|
}
|
|
339
355
|
lastArgExits = arg.exitPoints;
|
|
340
356
|
}
|
|
341
357
|
for (const exit of lastArgExits) {
|
|
342
|
-
graph.addEdge(callId
|
|
358
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(callId), exit, control_flow_graph_1.CfgEdge.makeFd());
|
|
343
359
|
}
|
|
344
360
|
if (call.named && call.functionName.content === 'return') {
|
|
345
|
-
info.returns.push(callId
|
|
361
|
+
info.returns.push(control_flow_graph_1.CfgVertex.toExitId(callId));
|
|
346
362
|
info.exitPoints.length = 0;
|
|
347
363
|
}
|
|
348
364
|
// should not contain any breaks, nexts, or returns, (except for the body if something like 'break()')
|
|
349
365
|
return info;
|
|
350
366
|
}
|
|
351
|
-
exports.ResolvedCallSuffix = '-resolved-call
|
|
367
|
+
exports.ResolvedCallSuffix = control_flow_graph_1.CfgVertex.toExitId('-resolved-call');
|
|
352
368
|
const OriginToFoldTypeMap = {
|
|
353
369
|
[built_in_1.BuiltInProcName.IfThenElse]: (folds, call, args) => {
|
|
354
370
|
// arguments are in order!
|
|
@@ -374,20 +390,21 @@ function cfgFunctionCallWithDataflow(graph, folds) {
|
|
|
374
390
|
for (const target of targets) {
|
|
375
391
|
// we have to filter out non-func-call targets as the call targets contains names and call ids
|
|
376
392
|
if ((0, vertex_1.isFunctionDefinitionVertex)(graph.getVertex(target))) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
393
|
+
const ct = control_flow_graph_1.CfgVertex.getCallTargets(callVertex);
|
|
394
|
+
if (!ct) {
|
|
395
|
+
control_flow_graph_1.CfgVertex.setCallTargets(callVertex, new Set([target]));
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
ct.add(target);
|
|
399
|
+
}
|
|
400
|
+
exits.push(control_flow_graph_1.CfgVertex.toExitId(target));
|
|
380
401
|
}
|
|
381
402
|
}
|
|
382
403
|
if (exits.length > 0) {
|
|
383
|
-
baseCfg.graph.addVertex(
|
|
384
|
-
id: call.info.id + exports.ResolvedCallSuffix,
|
|
385
|
-
type: control_flow_graph_1.CfgVertexType.EndMarker,
|
|
386
|
-
root: call.info.id
|
|
387
|
-
});
|
|
404
|
+
baseCfg.graph.addVertex(control_flow_graph_1.CfgVertex.makeMarker(call.info.id + exports.ResolvedCallSuffix, call.info.id));
|
|
388
405
|
for (const col of [baseCfg.exitPoints, exits]) {
|
|
389
406
|
for (const exit of col) {
|
|
390
|
-
baseCfg.graph.addEdge(call.info.id + exports.ResolvedCallSuffix, exit,
|
|
407
|
+
baseCfg.graph.addEdge(call.info.id + exports.ResolvedCallSuffix, exit, control_flow_graph_1.CfgEdge.makeFd());
|
|
391
408
|
}
|
|
392
409
|
}
|
|
393
410
|
return {
|
|
@@ -402,16 +419,17 @@ function cfgFunctionCallWithDataflow(graph, folds) {
|
|
|
402
419
|
}
|
|
403
420
|
function cfgArgumentOrParameter(node, name, value) {
|
|
404
421
|
const graph = new control_flow_graph_1.ControlFlowGraph();
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
422
|
+
const nodeId = node.info.id;
|
|
423
|
+
const info = { graph, breaks: [], nexts: [], returns: [], exitPoints: [control_flow_graph_1.CfgVertex.toExitId(nodeId)], entryPoints: [nodeId] };
|
|
424
|
+
let currentExitPoints = name?.exitPoints ?? [nodeId];
|
|
425
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExpressionWithEnd(nodeId, { mid: currentExitPoints }));
|
|
408
426
|
if (name) {
|
|
409
427
|
graph.mergeWith(name.graph);
|
|
410
428
|
info.breaks = info.breaks.concat(name.breaks);
|
|
411
429
|
info.nexts = info.nexts.concat(name.nexts);
|
|
412
430
|
info.returns = info.returns.concat(name.returns);
|
|
413
431
|
for (const entry of name.entryPoints) {
|
|
414
|
-
graph.addEdge(entry,
|
|
432
|
+
graph.addEdge(entry, nodeId, control_flow_graph_1.CfgEdge.makeFd());
|
|
415
433
|
}
|
|
416
434
|
}
|
|
417
435
|
if (value) {
|
|
@@ -421,42 +439,46 @@ function cfgArgumentOrParameter(node, name, value) {
|
|
|
421
439
|
info.returns = info.returns.concat(value.returns);
|
|
422
440
|
for (const exitPoint of currentExitPoints) {
|
|
423
441
|
for (const entry of value.entryPoints) {
|
|
424
|
-
graph.addEdge(entry, exitPoint,
|
|
442
|
+
graph.addEdge(entry, exitPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
425
443
|
}
|
|
426
444
|
}
|
|
427
445
|
currentExitPoints = value.exitPoints;
|
|
428
446
|
}
|
|
429
|
-
graph.addVertex(
|
|
447
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(nodeId));
|
|
430
448
|
for (const exit of currentExitPoints) {
|
|
431
|
-
graph.addEdge(
|
|
449
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(nodeId), exit, control_flow_graph_1.CfgEdge.makeFd());
|
|
432
450
|
}
|
|
433
451
|
return info;
|
|
434
452
|
}
|
|
435
453
|
function cfgBinaryOp(binOp, lhs, rhs) {
|
|
436
|
-
const graph =
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
454
|
+
const graph = lhs.graph.mergeWith(rhs.graph);
|
|
455
|
+
const binId = binOp.info.id;
|
|
456
|
+
const binExit = control_flow_graph_1.CfgVertex.toExitId(binId);
|
|
457
|
+
const result = { graph, breaks: lhs.breaks.concat(rhs.breaks), nexts: lhs.nexts.concat(rhs.nexts), returns: lhs.returns.concat(rhs.returns), entryPoints: [binId], exitPoints: [binExit] };
|
|
458
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(binId, binOp.flavor === 'assignment' ? control_flow_graph_1.CfgVertexType.Statement : control_flow_graph_1.CfgVertexType.Expression, { end: [binExit] }));
|
|
459
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(binId));
|
|
460
|
+
const fd = control_flow_graph_1.CfgEdge.makeFd();
|
|
440
461
|
for (const exitPoint of lhs.exitPoints) {
|
|
441
462
|
for (const entryPoint of rhs.entryPoints) {
|
|
442
|
-
result.graph.addEdge(entryPoint, exitPoint,
|
|
463
|
+
result.graph.addEdge(entryPoint, exitPoint, fd);
|
|
443
464
|
}
|
|
444
465
|
}
|
|
445
466
|
for (const entryPoint of lhs.entryPoints) {
|
|
446
|
-
graph.addEdge(entryPoint,
|
|
467
|
+
graph.addEdge(entryPoint, binId, fd);
|
|
447
468
|
}
|
|
448
469
|
for (const exitPoint of rhs.exitPoints) {
|
|
449
|
-
graph.addEdge(
|
|
470
|
+
graph.addEdge(binExit, exitPoint, fd);
|
|
450
471
|
}
|
|
451
472
|
return result;
|
|
452
473
|
}
|
|
453
474
|
function cfgAccess(access, name, accessors) {
|
|
454
475
|
const result = { ...name };
|
|
455
476
|
const graph = result.graph;
|
|
456
|
-
|
|
457
|
-
|
|
477
|
+
const accessId = access.info.id;
|
|
478
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExpressionWithEnd(accessId, { mid: name.exitPoints }));
|
|
479
|
+
result.entryPoints = [accessId];
|
|
458
480
|
for (const entry of name.entryPoints) {
|
|
459
|
-
graph.addEdge(entry,
|
|
481
|
+
graph.addEdge(entry, accessId, control_flow_graph_1.CfgEdge.makeFd());
|
|
460
482
|
}
|
|
461
483
|
result.exitPoints = name.exitPoints;
|
|
462
484
|
for (const accessor of accessors) {
|
|
@@ -466,7 +488,7 @@ function cfgAccess(access, name, accessors) {
|
|
|
466
488
|
graph.mergeWith(accessor.graph);
|
|
467
489
|
for (const exitPoint of result.exitPoints) {
|
|
468
490
|
for (const entry of accessor.entryPoints) {
|
|
469
|
-
graph.addEdge(entry, exitPoint,
|
|
491
|
+
graph.addEdge(entry, exitPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
470
492
|
}
|
|
471
493
|
}
|
|
472
494
|
result.exitPoints = accessor.exitPoints;
|
|
@@ -475,58 +497,56 @@ function cfgAccess(access, name, accessors) {
|
|
|
475
497
|
result.returns = result.returns.concat(accessor.returns);
|
|
476
498
|
}
|
|
477
499
|
for (const exitPoint of result.exitPoints) {
|
|
478
|
-
graph.addEdge(
|
|
500
|
+
graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(accessId), exitPoint, control_flow_graph_1.CfgEdge.makeFd());
|
|
479
501
|
}
|
|
480
|
-
graph.addVertex(
|
|
481
|
-
result.exitPoints = [
|
|
502
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(accessId));
|
|
503
|
+
result.exitPoints = [control_flow_graph_1.CfgVertex.toExitId(accessId)];
|
|
482
504
|
return result;
|
|
483
505
|
}
|
|
484
506
|
function cfgUnaryOp(unary, operand) {
|
|
485
507
|
const graph = operand.graph;
|
|
486
|
-
|
|
508
|
+
const unaryId = unary.info.id;
|
|
509
|
+
graph.addVertex(control_flow_graph_1.CfgVertex.makeMarker(unaryId, unaryId));
|
|
510
|
+
const fd = control_flow_graph_1.CfgEdge.makeFd();
|
|
487
511
|
for (const entry of operand.exitPoints) {
|
|
488
|
-
graph.addEdge(
|
|
512
|
+
graph.addEdge(unaryId, entry, fd);
|
|
489
513
|
}
|
|
490
|
-
return { ...operand, graph, exitPoints: [
|
|
514
|
+
return { ...operand, graph, exitPoints: [unaryId] };
|
|
491
515
|
}
|
|
492
516
|
function cfgExprList(node, _grouping, expressions) {
|
|
517
|
+
const nodeId = node.info.id;
|
|
493
518
|
const result = {
|
|
494
519
|
graph: new control_flow_graph_1.ControlFlowGraph(),
|
|
495
520
|
breaks: [],
|
|
496
521
|
nexts: [],
|
|
497
522
|
returns: [],
|
|
498
|
-
exitPoints: [
|
|
499
|
-
entryPoints: [
|
|
523
|
+
exitPoints: [nodeId],
|
|
524
|
+
entryPoints: [nodeId]
|
|
500
525
|
};
|
|
501
|
-
const vtx =
|
|
526
|
+
const vtx = control_flow_graph_1.CfgVertex.makeExpression(nodeId);
|
|
502
527
|
result.graph.addVertex(vtx);
|
|
528
|
+
const fd = control_flow_graph_1.CfgEdge.makeFd();
|
|
503
529
|
for (const expression of expressions) {
|
|
504
530
|
for (const previousExitPoint of result.exitPoints) {
|
|
505
531
|
for (const entryPoint of expression.entryPoints) {
|
|
506
|
-
result.graph.addEdge(entryPoint, previousExitPoint,
|
|
532
|
+
result.graph.addEdge(entryPoint, previousExitPoint, fd);
|
|
507
533
|
}
|
|
508
534
|
}
|
|
509
535
|
result.graph.mergeWith(expression.graph);
|
|
510
|
-
result.breaks
|
|
511
|
-
result.nexts
|
|
512
|
-
result.returns
|
|
536
|
+
result.breaks.push(...expression.breaks);
|
|
537
|
+
result.nexts.push(...expression.nexts);
|
|
538
|
+
result.returns.push(...expression.returns);
|
|
513
539
|
result.exitPoints = expression.exitPoints;
|
|
514
540
|
}
|
|
541
|
+
const exitId = control_flow_graph_1.CfgVertex.toExitId(nodeId);
|
|
515
542
|
if (result.exitPoints.length > 0) {
|
|
516
|
-
result.graph.addVertex(
|
|
517
|
-
|
|
518
|
-
type: control_flow_graph_1.CfgVertexType.EndMarker,
|
|
519
|
-
root: node.info.id
|
|
520
|
-
});
|
|
521
|
-
vtx.end = [node.info.id + '-exit'];
|
|
522
|
-
}
|
|
523
|
-
else {
|
|
524
|
-
vtx.end = undefined;
|
|
543
|
+
result.graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(nodeId));
|
|
544
|
+
control_flow_graph_1.CfgVertex.setEnd(vtx, [exitId]);
|
|
525
545
|
}
|
|
526
546
|
for (const exit of result.exitPoints) {
|
|
527
|
-
result.graph.addEdge(
|
|
547
|
+
result.graph.addEdge(exitId, exit, fd);
|
|
528
548
|
}
|
|
529
|
-
result.exitPoints = result.exitPoints.length > 0 ? [
|
|
549
|
+
result.exitPoints = result.exitPoints.length > 0 ? [exitId] : [];
|
|
530
550
|
return result;
|
|
531
551
|
}
|
|
532
552
|
/**
|
|
@@ -541,13 +561,13 @@ function cfg2quads(cfg, config) {
|
|
|
541
561
|
vertices: [...cfg.graph.vertices().entries()]
|
|
542
562
|
.map(([id, v]) => ({
|
|
543
563
|
id,
|
|
544
|
-
children: v
|
|
564
|
+
children: control_flow_graph_1.CfgVertex.getChildren(v)
|
|
545
565
|
})),
|
|
546
566
|
edges: [...cfg.graph.edges()].flatMap(([fromId, targets]) => [...targets].map(([toId, info]) => ({
|
|
547
567
|
from: fromId,
|
|
548
568
|
to: toId,
|
|
549
|
-
type: info
|
|
550
|
-
when: info
|
|
569
|
+
type: control_flow_graph_1.CfgEdge.getType(info),
|
|
570
|
+
when: control_flow_graph_1.CfgEdge.getWhen(info)
|
|
551
571
|
}))),
|
|
552
572
|
entryPoints: cfg.entryPoints,
|
|
553
573
|
exitPoints: cfg.exitPoints,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.happensBefore = happensBefore;
|
|
4
4
|
const logic_1 = require("../util/logic");
|
|
5
|
+
const control_flow_graph_1 = require("./control-flow-graph");
|
|
5
6
|
/**
|
|
6
7
|
* Determines if node `a` happens before node `b` in the control flow graph.
|
|
7
8
|
*/
|
|
@@ -23,7 +24,7 @@ function happensBefore(cfg, a, b) {
|
|
|
23
24
|
}
|
|
24
25
|
visited.add(current);
|
|
25
26
|
for (const [id, t] of cfg.outgoingEdges(current) ?? []) {
|
|
26
|
-
const marker =
|
|
27
|
+
const marker = control_flow_graph_1.CfgEdge.isControlDependency(t) ? control_flow_graph_1.CfgVertex.toExitId(control_flow_graph_1.CfgEdge.unpackCause(t)) : useCd;
|
|
27
28
|
stack.push([id, useCd ?? marker]);
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SemanticCfgGuidedVisitor = void 0;
|
|
4
|
+
const control_flow_graph_1 = require("./control-flow-graph");
|
|
4
5
|
const dfg_cfg_guided_visitor_1 = require("./dfg-cfg-guided-visitor");
|
|
5
6
|
const dfg_get_origin_1 = require("../dataflow/origin/dfg-get-origin");
|
|
6
7
|
const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
|
|
@@ -132,7 +133,7 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
|
|
|
132
133
|
*/
|
|
133
134
|
visitUnknown(vertex) {
|
|
134
135
|
super.visitUnknown(vertex);
|
|
135
|
-
const ast = this.getNormalizedAst(vertex
|
|
136
|
+
const ast = this.getNormalizedAst(control_flow_graph_1.CfgVertex.getId(vertex));
|
|
136
137
|
if (ast && ast.type === type_1.RType.ExpressionList && ast.info.parent === undefined) {
|
|
137
138
|
this.onProgram(ast);
|
|
138
139
|
}
|
|
@@ -30,9 +30,10 @@ visitor) {
|
|
|
30
30
|
}
|
|
31
31
|
else if (hasBb) {
|
|
32
32
|
const get = graph.getVertex(current);
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if (control_flow_graph_1.CfgVertex.isBlock(get)) {
|
|
34
|
+
const elems = control_flow_graph_1.CfgVertex.getBasicBlockElements(get);
|
|
35
|
+
for (const e of elems.toReversed()) {
|
|
36
|
+
queue.push(control_flow_graph_1.CfgVertex.getId(e));
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -70,9 +71,10 @@ visitor) {
|
|
|
70
71
|
}
|
|
71
72
|
else if (hasBb) {
|
|
72
73
|
const get = graph.getVertex(current);
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
if (control_flow_graph_1.CfgVertex.isBlock(get)) {
|
|
75
|
+
const elems = control_flow_graph_1.CfgVertex.getBasicBlockElements(get);
|
|
76
|
+
for (const e of elems.toReversed()) {
|
|
77
|
+
queue.push(control_flow_graph_1.CfgVertex.getId(e));
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SyntaxAwareCfgGuidedVisitor = void 0;
|
|
4
|
+
const control_flow_graph_1 = require("./control-flow-graph");
|
|
4
5
|
const basic_cfg_guided_visitor_1 = require("./basic-cfg-guided-visitor");
|
|
5
6
|
const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
|
|
6
7
|
const assert_1 = require("../util/assert");
|
|
@@ -25,7 +26,7 @@ class SyntaxAwareCfgGuidedVisitor extends basic_cfg_guided_visitor_1.BasicCfgGui
|
|
|
25
26
|
this.onExprOrStmtNode(node);
|
|
26
27
|
}
|
|
27
28
|
onExprOrStmtNode(node) {
|
|
28
|
-
const astVertex = this.getNormalizedAst(node
|
|
29
|
+
const astVertex = this.getNormalizedAst(control_flow_graph_1.CfgVertex.getId(node));
|
|
29
30
|
if (!astVertex) {
|
|
30
31
|
return;
|
|
31
32
|
}
|