Skip to content

Commit

Permalink
Merge pull request #129 from specs-feup/cfg-improvements
Browse files Browse the repository at this point in the history
New cfg config option to keep temporary statements + Update to C API test 'CfgApi'
  • Loading branch information
joaobispo authored Aug 15, 2023
2 parents ec9f9e4 + f4d1f37 commit 26b3e30
Show file tree
Hide file tree
Showing 5 changed files with 581 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ class ControlFlowGraph extends Graph {
*
* @param {joinpoint} $jp
* @param {boolean} [deterministicIds = false] If true, uses deterministic ids for the graph ids (e.g. id_0, id_1...). Otherwise, uses $jp.astId whenever possible
* @param {Object} [options = {}] An object containing configuration options for the cfg
* @param {Object} [options = {}] An object containing configuration options for the cfg
* @param {boolean} [options.splitInstList = false] If true, statements of each instruction list must be split
* @param {boolean} [options.removeGotoNodes = false] If true, the nodes that correspond to goto statements will be excluded from the resulting graph
* @param {boolean} [options.removeLabelNodes = false] If true, the nodes that correspond to label statements will be excluded from the resulting graph
*
* @param {boolean} [options.keepTemporaryScopeStmts = false] If true, the temporary scope statements will be kept in the resulting graph
* @returns {ControlFlowGraph} a new instance of the ControlFlowGraph class
*/
static build($jp, deterministicIds = false, options = {}) {
Expand Down
26 changes: 19 additions & 7 deletions ClavaLaraApi/src-lara-clava/clava/clava/graphs/cfg/CfgBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,28 @@ class CfgBuilder {
*/
#removeLabelNodes;

/**
* {boolean} If true, the temporary scope statements should not be removed from the graph
*/
#keepTemporaryScopeStmts;

/**
* Creates a new instance of the CfgBuilder class
* @param {joinpoint} $jp
* @param {boolean} [deterministicIds = false] If true, uses deterministic ids for the graph ids (e.g. id_0, id_1...). Otherwise, uses $jp.astId whenever possible
* @param {Object} [options = {}] An object containing configuration options for the cfg
* @param {Object} [options = {}] An object containing configuration options for the cfg
* @param {boolean} [options.splitInstList = false] If true, statements of each instruction list must be split
* @param {boolean} [options.removeGotoNodes = false] If true, the nodes that correspond to goto statements will be excluded from the resulting graph
* @param {boolean} [options.removeLabelNodes = false] If true, the nodes that correspond to label statements will be excluded from the resulting graph
* @param {boolean} [options.keepTemporaryScopeStmts = false] If true, the temporary scope statements will be kept in the resulting graph
*/
constructor($jp, deterministicIds = false, options = {}) {
this.#jp = $jp;
this.#deterministicIds = deterministicIds;
this.#splitInstList = options.splitInstList || false;
this.#removeGotoNodes = options.removeGotoNodes || false;
this.#removeLabelNodes = options.removeLabelNodes || false;
this.#splitInstList = options.splitInstList ?? false;
this.#removeGotoNodes = options.removeGotoNodes ?? false;
this.#removeLabelNodes = options.removeLabelNodes ?? false;
this.#keepTemporaryScopeStmts = options.keepTemporaryScopeStmts ?? false;
this.#currentId = 0;
this.#dataFactory = new DataFactory(this.#jp);
this.#graph = Graphs.newGraph();
Expand Down Expand Up @@ -558,10 +565,12 @@ class CfgBuilder {

_cleanCfg() {
// Remove temporary instructions from the code
for (const stmtId in this.#temporaryStmts) {
this.#temporaryStmts[stmtId].detach();
if (!this.#keepTemporaryScopeStmts) {
for (const stmtId in this.#temporaryStmts) {
this.#temporaryStmts[stmtId].detach();
}
}

// Remove temporary instructions from the instList nodes and this.#nodes
for (const node of this.#nodes.values()) {
// Only inst lists need to be cleaned
Expand All @@ -581,6 +590,9 @@ class CfgBuilder {

// Filter stmts that are temporary statements

if (this.#keepTemporaryScopeStmts)
continue;

const filteredStmts = [];
for (const $stmt of node.data().stmts) {
// If not a temporary stmt, add to filtered list
Expand Down
30 changes: 24 additions & 6 deletions ClavaWeaver/resources/clava/test/api/CfgApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ laraImport("clava.graphs.cfg.CfgUtils");
laraImport("clava.graphs.cfg.CfgEdgeType");
laraImport("weaver.Query");

const $fooFunction = Query.search("function", "foo").first();
const cfg = ControlFlowGraph.build($fooFunction, true);
println("Graph for foo:");
println(Graphs.toDot(cfg.graph));
verifyGraph(cfg)
println("Verification done")
const $functions = Query.search("function");
for (const $function of $functions) {
buildAndVerifyCfg($function);
}

const $gotoLabelFunction = Query.search("function", "gotoAndLabelExample").first();
const cfgOptions = {splitInstList: true,
removeLabelNodes: true,
removeGotoNodes: true,
keepTemporaryScopeStmts: true};
buildAndVerifyCfg($gotoLabelFunction, cfgOptions);

// Stress test
for(const $stmt of Query.search("function", "foo").search("statement")) {
Expand All @@ -18,7 +23,20 @@ for(const $stmt of Query.search("function", "foo").search("statement")) {
// println(Graphs.toDot(smallCfg.graph));
}

function buildAndVerifyCfg($function, options) {
const cfg = ControlFlowGraph.build($function, true, options);

if (options !== undefined) {
println(`Options used and Graph for ${$function.name}:`)
println(`${JSON.stringify(options, null, 2)}`);
}
else
println(`Graph for ${$function.name}:`)

println(Graphs.toDot(cfg.graph));
verifyGraph(cfg)
println(`Verification completed for ${$function.name}\n`)
}

function verifyGraph(cfg) {
for(const node of cfg.graph.nodes()) {
Expand Down
Loading

0 comments on commit 26b3e30

Please sign in to comment.