From 9408c2736df043580114b3f2a82ff80d1d89e3fb Mon Sep 17 00:00:00 2001 From: Milena Gouveia Date: Mon, 7 Aug 2023 16:02:39 +0100 Subject: [PATCH 1/3] [ClavaLaraApi] Add new config option to keep temporary stmts of the cfg --- .../clava/clava/graphs/ControlFlowGraph.js | 4 +-- .../clava/clava/graphs/cfg/CfgBuilder.js | 26 ++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js b/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js index 3f4b853a2..2dc18faa0 100644 --- a/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js +++ b/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js @@ -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 = true] 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 = {}) { diff --git a/ClavaLaraApi/src-lara-clava/clava/clava/graphs/cfg/CfgBuilder.js b/ClavaLaraApi/src-lara-clava/clava/clava/graphs/cfg/CfgBuilder.js index 004db79f7..01cd0a74e 100644 --- a/ClavaLaraApi/src-lara-clava/clava/clava/graphs/cfg/CfgBuilder.js +++ b/ClavaLaraApi/src-lara-clava/clava/clava/graphs/cfg/CfgBuilder.js @@ -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(); @@ -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 @@ -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 From 14dae509aa4164d0d5e5f96a75cfde9fbec84020 Mon Sep 17 00:00:00 2001 From: Milena Gouveia Date: Wed, 9 Aug 2023 16:23:50 +0100 Subject: [PATCH 2/3] [ClavaWeaver] Update CfgApi test to validate the new cfg improvements --- .../resources/clava/test/api/CfgApi.js | 30 +- .../clava/test/api/c/results/CfgApi.js.txt | 326 +++++++++++++++++- .../resources/clava/test/api/c/src/cfg_api.c | 212 +++++++++++- 3 files changed, 560 insertions(+), 8 deletions(-) diff --git a/ClavaWeaver/resources/clava/test/api/CfgApi.js b/ClavaWeaver/resources/clava/test/api/CfgApi.js index b96261b5d..dd0d5fcf1 100644 --- a/ClavaWeaver/resources/clava/test/api/CfgApi.js +++ b/ClavaWeaver/resources/clava/test/api/CfgApi.js @@ -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")) { @@ -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()) { diff --git a/ClavaWeaver/resources/clava/test/api/c/results/CfgApi.js.txt b/ClavaWeaver/resources/clava/test/api/c/results/CfgApi.js.txt index 75464935f..00a3c3ce7 100644 --- a/ClavaWeaver/resources/clava/test/api/c/results/CfgApi.js.txt +++ b/ClavaWeaver/resources/clava/test/api/c/results/CfgApi.js.txt @@ -170,4 +170,328 @@ digraph test { "id_68" -> "id_70" [label="TRUE"]; "id_68" -> "id_79" [label="FALSE"]; } -Verification done \ No newline at end of file +Verification completed for foo + +Graph for breakAndContinueExample: +digraph test { +"start" [label="Start" shape=box]; +"end" [label="End" shape=box]; +"id_0" [label="Scope" shape=box]; +"id_2" [label="Loop: for" shape=box]; +"id_3" [label="Init: int k = 0;" shape=box]; +"id_4" [label="Cond: k < 4;" shape=box]; +"id_5" [label="Step: k++;" shape=box]; +"id_6" [label="Scope" shape=box]; +"id_7" [label="int forLoop1;\l" shape=box]; +"id_8" [label="Loop: for" shape=box]; +"id_9" [label="Init: int j = 0;" shape=box]; +"id_10" [label="Cond: j < 4;" shape=box]; +"id_11" [label="Step: j++;" shape=box]; +"id_12" [label="Scope" shape=box]; +"id_13" [label="int forLoop2;\lint ifStmt;\l" shape=box]; +"id_14" [label="if(j > k)" shape=box]; +"id_15" [label="Then" shape=box]; +"id_16" [label="int thenBody;\l" shape=box]; +"id_17" [label="Break" shape=box]; +"id_19" [label="Else" shape=box]; +"id_21" [label="if(j == k)" shape=box]; +"id_22" [label="Then" shape=box]; +"id_23" [label="int elseBody;\l" shape=box]; +"id_24" [label="Continue" shape=box]; +"id_27" [label="int afterIfStmt;\l" shape=box]; +"id_28" [label="int afterForLoop2;\l" shape=box]; +"id_29" [label="int afterForLoop1;\lint whileLoop;\lint a = 10;\l" shape=box]; +"id_30" [label="Loop: while" shape=box]; +"id_31" [label="Cond: a > 0;" shape=box]; +"id_32" [label="Scope" shape=box]; +"id_33" [label="int whileBody;\lint ifStmt2;\l" shape=box]; +"id_34" [label="if(1)" shape=box]; +"id_35" [label="Then" shape=box]; +"id_36" [label="a--;\l" shape=box]; +"id_37" [label="Continue" shape=box]; +"id_39" [label="int afterIfStmt2;\la--;\l" shape=box]; +"id_40" [label="int afterWhile;\lint doWhileLoop;\lint b = 10;\l" shape=box]; +"id_41" [label="Loop: dowhile" shape=box]; +"id_42" [label="Scope" shape=box]; +"id_43" [label="int whileBody;\lint ifStmt3;\l" shape=box]; +"id_44" [label="if(1)" shape=box]; +"id_45" [label="Then" shape=box]; +"id_46" [label="b--;\l" shape=box]; +"id_47" [label="Continue" shape=box]; +"id_49" [label="int afterIfStmt3;\lb--;\l" shape=box]; +"id_50" [label="Cond: b > 0;" shape=box]; +"id_51" [label="int afterDoWhile;\l" shape=box]; +"id_50" -> "id_51" [label="FALSE"]; +"id_49" -> "id_50" [label=""]; +"id_47" -> "id_50" [label=""]; +"id_45" -> "id_46" [label=""]; +"id_44" -> "id_45" [label="TRUE"]; +"id_42" -> "id_43" [label=""]; +"id_40" -> "id_41" [label=""]; +"start" -> "id_0" [label=""]; +"id_51" -> "end" [label=""]; +"id_0" -> "id_2" [label=""]; +"id_2" -> "id_3" [label=""]; +"id_3" -> "id_4" [label=""]; +"id_4" -> "id_6" [label="TRUE"]; +"id_4" -> "id_29" [label="FALSE"]; +"id_5" -> "id_4" [label=""]; +"id_6" -> "id_7" [label=""]; +"id_7" -> "id_8" [label=""]; +"id_8" -> "id_9" [label=""]; +"id_9" -> "id_10" [label=""]; +"id_10" -> "id_12" [label="TRUE"]; +"id_10" -> "id_28" [label="FALSE"]; +"id_11" -> "id_10" [label=""]; +"id_12" -> "id_13" [label=""]; +"id_13" -> "id_14" [label=""]; +"id_14" -> "id_15" [label="TRUE"]; +"id_14" -> "id_19" [label="FALSE"]; +"id_15" -> "id_16" [label=""]; +"id_16" -> "id_17" [label=""]; +"id_17" -> "id_28" [label=""]; +"id_50" -> "id_42" [label="TRUE"]; +"id_41" -> "id_42" [label=""]; +"id_19" -> "id_21" [label=""]; +"id_21" -> "id_22" [label="TRUE"]; +"id_44" -> "id_49" [label="FALSE"]; +"id_22" -> "id_23" [label=""]; +"id_23" -> "id_24" [label=""]; +"id_24" -> "id_11" [label=""]; +"id_46" -> "id_47" [label=""]; +"id_21" -> "id_27" [label="FALSE"]; +"id_27" -> "id_11" [label=""]; +"id_28" -> "id_5" [label=""]; +"id_29" -> "id_30" [label=""]; +"id_30" -> "id_31" [label=""]; +"id_31" -> "id_32" [label="TRUE"]; +"id_31" -> "id_40" [label="FALSE"]; +"id_32" -> "id_33" [label=""]; +"id_33" -> "id_34" [label=""]; +"id_34" -> "id_35" [label="TRUE"]; +"id_34" -> "id_39" [label="FALSE"]; +"id_35" -> "id_36" [label=""]; +"id_36" -> "id_37" [label=""]; +"id_37" -> "id_31" [label=""]; +"id_43" -> "id_44" [label=""]; +"id_39" -> "id_31" [label=""]; +} +Verification completed for breakAndContinueExample + +Graph for switchCaseExample: +digraph test { +"start" [label="Start" shape=box]; +"end" [label="End" shape=box]; +"id_0" [label="Scope" shape=box]; +"id_1" [label="int a = 10;\lint switch1, result1;\lint defaultOnly;\l" shape=box]; +"id_2" [label="switch(a)" shape=box]; +"id_5" [label="default:\l" shape=box]; +"id_6" [label="result1 = 20;\lint switch1DefaultInst1;\lint switch1DefaultInst2;\l" shape=box]; +"id_7" [label="Break" shape=box]; +"id_9" [label="int afterDefaultOnly;\lint afterSwitch1;\lint switch2, result2;\lint noDefault;\l" shape=box]; +"id_10" [label="switch(a)" shape=box]; +"id_13" [label="case 1:\l" shape=box]; +"id_14" [label="result2 = 1;\lint switch2Case1Inst1;\lint switch2Case1Inst2;\l" shape=box]; +"id_15" [label="Break" shape=box]; +"id_16" [label="case 3:\l" shape=box]; +"id_17" [label="result2 = 3;\lint switch2Case3Inst1;\lint switch2Case3Inst2;\l" shape=box]; +"id_18" [label="Break" shape=box]; +"id_19" [label="case 4 ... 8:\l" shape=box]; +"id_20" [label="result2 = 48;\lint switch2RangeCaseInst1;\lint switch2RangeCaseInst2;\l" shape=box]; +"id_21" [label="Break" shape=box]; +"id_23" [label="int afterNoDefault;\lint afterSwitch2;\lint switch3, result3;\lint withDefault;\l" shape=box]; +"id_24" [label="switch(a)" shape=box]; +"id_27" [label="case 1:\l" shape=box]; +"id_28" [label="result3 = 1;\lint switch3Case1Inst1;\lint switch3Case1Inst2;\l" shape=box]; +"id_29" [label="Break" shape=box]; +"id_30" [label="case 3:\l" shape=box]; +"id_31" [label="result3 = 3;\lint switch3Case3Inst1;\lint switch3Case3Inst2;\l" shape=box]; +"id_32" [label="Break" shape=box]; +"id_33" [label="case 4 ... 8:\l" shape=box]; +"id_34" [label="result3 = 48;\lint switch2RangeCaseInst1;\lint switch2RangeCaseInst2;\l" shape=box]; +"id_35" [label="Break" shape=box]; +"id_36" [label="default:\l" shape=box]; +"id_37" [label="result3 = 20;\lint switch3DefaultInst1;\lint switch3DefaultInst2;\l" shape=box]; +"id_38" [label="Break" shape=box]; +"id_40" [label="int afterWithDefault;\lint afterSwitch3;\lint switch4, result4;\lint intermediateDefault;\l" shape=box]; +"id_41" [label="switch(a)" shape=box]; +"id_44" [label="case 1:\l" shape=box]; +"id_45" [label="result4 = 1;\lint switch4Case1Inst1;\lint switch4Case1Inst2;\l" shape=box]; +"id_46" [label="Break" shape=box]; +"id_47" [label="default:\l" shape=box]; +"id_48" [label="result4 = 20;\lint switch4DefaultInst1;\lint switch4DefaultInst2;\l" shape=box]; +"id_49" [label="Break" shape=box]; +"id_50" [label="case 3:\l" shape=box]; +"id_51" [label="result4 = 3;\lint switch4Case3Inst1;\lint switch4Case3Inst2;\l" shape=box]; +"id_52" [label="Break" shape=box]; +"id_54" [label="int afterIntermediateDefault;\lint afterSwitch4;\lint switch5, result5;\lint noBreak;\l" shape=box]; +"id_55" [label="switch(a)" shape=box]; +"id_58" [label="case 1:\l" shape=box]; +"id_59" [label="result5 = 1;\lint switch5Case1Inst1;\lint switch5Case1Inst2;\l" shape=box]; +"id_60" [label="if(1)" shape=box]; +"id_61" [label="Then" shape=box]; +"id_62" [label="int ifBody;\l" shape=box]; +"id_63" [label="Break" shape=box]; +"id_65" [label="case 2:\l" shape=box]; +"id_66" [label="result5 = 2;\lint switch5Case2Inst1;\lint switch5Case2Inst2;\l" shape=box]; +"id_67" [label="default:\l" shape=box]; +"id_68" [label="result5 = 20;\lint switch5DefaultInst1;\lint switch5DefaultInst2;\l" shape=box]; +"id_69" [label="case 3:\l" shape=box]; +"id_70" [label="result5 = 3;\lint switch5Case3Inst1;\lint switch5Case3Inst2;\l" shape=box]; +"id_71" [label="int afterNoBreak;\lint afterSwitch5;\l" shape=box]; +"id_72" [label="return 0;" shape=box]; +"id_54" -> "id_55" [label=""]; +"id_72" -> "end" [label=""]; +"id_70" -> "id_71" [label=""]; +"id_52" -> "id_54" [label=""]; +"id_69" -> "id_70" [label="TRUE"]; +"id_67" -> "id_68" [label=""]; +"id_50" -> "id_47" [label="FALSE"]; +"id_65" -> "id_69" [label="FALSE"]; +"id_58" -> "id_65" [label="FALSE"]; +"id_49" -> "id_54" [label=""]; +"id_62" -> "id_63" [label=""]; +"id_60" -> "id_66" [label="FALSE"]; +"id_47" -> "id_48" [label=""]; +"id_59" -> "id_60" [label=""]; +"id_58" -> "id_59" [label="TRUE"]; +"id_60" -> "id_61" [label="TRUE"]; +"start" -> "id_0" [label=""]; +"id_0" -> "id_1" [label=""]; +"id_1" -> "id_2" [label=""]; +"id_2" -> "id_5" [label=""]; +"id_48" -> "id_49" [label=""]; +"id_55" -> "id_58" [label=""]; +"id_5" -> "id_6" [label=""]; +"id_6" -> "id_7" [label=""]; +"id_7" -> "id_9" [label=""]; +"id_71" -> "id_72" [label=""]; +"id_9" -> "id_10" [label=""]; +"id_10" -> "id_13" [label=""]; +"id_69" -> "id_67" [label="FALSE"]; +"id_61" -> "id_62" [label=""]; +"id_13" -> "id_14" [label="TRUE"]; +"id_13" -> "id_16" [label="FALSE"]; +"id_14" -> "id_15" [label=""]; +"id_15" -> "id_23" [label=""]; +"id_16" -> "id_17" [label="TRUE"]; +"id_16" -> "id_19" [label="FALSE"]; +"id_17" -> "id_18" [label=""]; +"id_18" -> "id_23" [label=""]; +"id_19" -> "id_20" [label="TRUE"]; +"id_19" -> "id_23" [label="FALSE"]; +"id_20" -> "id_21" [label=""]; +"id_21" -> "id_23" [label=""]; +"id_68" -> "id_70" [label=""]; +"id_23" -> "id_24" [label=""]; +"id_24" -> "id_27" [label=""]; +"id_66" -> "id_68" [label=""]; +"id_51" -> "id_52" [label=""]; +"id_27" -> "id_28" [label="TRUE"]; +"id_27" -> "id_30" [label="FALSE"]; +"id_28" -> "id_29" [label=""]; +"id_29" -> "id_40" [label=""]; +"id_30" -> "id_31" [label="TRUE"]; +"id_30" -> "id_33" [label="FALSE"]; +"id_31" -> "id_32" [label=""]; +"id_32" -> "id_40" [label=""]; +"id_33" -> "id_34" [label="TRUE"]; +"id_33" -> "id_36" [label="FALSE"]; +"id_34" -> "id_35" [label=""]; +"id_35" -> "id_40" [label=""]; +"id_36" -> "id_37" [label=""]; +"id_37" -> "id_38" [label=""]; +"id_38" -> "id_40" [label=""]; +"id_65" -> "id_66" [label="TRUE"]; +"id_40" -> "id_41" [label=""]; +"id_41" -> "id_44" [label=""]; +"id_63" -> "id_71" [label=""]; +"id_50" -> "id_51" [label="TRUE"]; +"id_44" -> "id_45" [label="TRUE"]; +"id_44" -> "id_50" [label="FALSE"]; +"id_45" -> "id_46" [label=""]; +"id_46" -> "id_54" [label=""]; +} +Verification completed for switchCaseExample + +Graph for gotoAndLabelExample: +digraph test { +"start" [label="Start" shape=box]; +"end" [label="End" shape=box]; +"id_0" [label="Scope" shape=box]; +"id_1" [label="int x = 1, y, z, result;\l" shape=box]; +"id_2" [label="if(x == 1)" shape=box]; +"id_3" [label="Then" shape=box]; +"id_5" [label="goto label1;\l" shape=box]; +"id_7" [label="Else" shape=box]; +"id_9" [label="goto label2;\l" shape=box]; +"id_11" [label="label1:" shape=box]; +"id_12" [label="y = x * 2;\lz = y + 5;\l" shape=box]; +"id_13" [label="goto end;\l" shape=box]; +"id_14" [label="label2:" shape=box]; +"id_15" [label="y = x + 3;\lz = y - 2;\l" shape=box]; +"id_16" [label="end:" shape=box]; +"id_17" [label="result = y + z;\l" shape=box]; +"id_18" [label="return result;" shape=box]; +"id_18" -> "end" [label=""]; +"id_16" -> "id_17" [label=""]; +"id_14" -> "id_15" [label=""]; +"id_12" -> "id_13" [label=""]; +"id_13" -> "id_16" [label=""]; +"start" -> "id_0" [label=""]; +"id_0" -> "id_1" [label=""]; +"id_1" -> "id_2" [label=""]; +"id_2" -> "id_3" [label="TRUE"]; +"id_2" -> "id_7" [label="FALSE"]; +"id_11" -> "id_12" [label=""]; +"id_3" -> "id_5" [label=""]; +"id_5" -> "id_11" [label=""]; +"id_17" -> "id_18" [label=""]; +"id_15" -> "id_16" [label=""]; +"id_7" -> "id_9" [label=""]; +"id_9" -> "id_14" [label=""]; +} +Verification completed for gotoAndLabelExample + +Options used and Graph for gotoAndLabelExample: +{ + "splitInstList": true, + "removeLabelNodes": true, + "removeGotoNodes": true, + "keepTemporaryScopeStmts": true +} +digraph test { +"start" [label="Start" shape=box]; +"end" [label="End" shape=box]; +"id_0" [label="Scope" shape=box]; +"id_1" [label="//SCOPE_START\l\l" shape=box]; +"id_2" [label="int x = 1, y, z, result;\l" shape=box]; +"id_3" [label="if(x == 1)" shape=box]; +"id_4" [label="Then" shape=box]; +"id_5" [label="//SCOPE_START\l\l" shape=box]; +"id_8" [label="Else" shape=box]; +"id_9" [label="//SCOPE_START\l\l" shape=box]; +"id_13" [label="y = x * 2;\l" shape=box]; +"id_14" [label="z = y + 5;\l" shape=box]; +"id_17" [label="y = x + 3;\l" shape=box]; +"id_18" [label="z = y - 2;\l" shape=box]; +"id_20" [label="result = y + z;\l" shape=box]; +"id_21" [label="return result;" shape=box]; +"id_14" -> "id_20" [label=""]; +"id_8" -> "id_9" [label=""]; +"id_13" -> "id_14" [label=""]; +"id_5" -> "id_13" [label=""]; +"id_21" -> "end" [label=""]; +"id_20" -> "id_21" [label=""]; +"id_18" -> "id_20" [label=""]; +"id_17" -> "id_18" [label=""]; +"id_9" -> "id_17" [label=""]; +"start" -> "id_0" [label=""]; +"id_0" -> "id_1" [label=""]; +"id_1" -> "id_2" [label=""]; +"id_2" -> "id_3" [label=""]; +"id_3" -> "id_4" [label="TRUE"]; +"id_3" -> "id_8" [label="FALSE"]; +"id_4" -> "id_5" [label=""]; +} +Verification completed for gotoAndLabelExample \ No newline at end of file diff --git a/ClavaWeaver/resources/clava/test/api/c/src/cfg_api.c b/ClavaWeaver/resources/clava/test/api/c/src/cfg_api.c index 7ecda0332..11873f15a 100644 --- a/ClavaWeaver/resources/clava/test/api/c/src/cfg_api.c +++ b/ClavaWeaver/resources/clava/test/api/c/src/cfg_api.c @@ -96,4 +96,214 @@ int foo() { betweenFor = 0; return 20; -} \ No newline at end of file +} + +// 'break' and 'continue' statements +int breakAndContinueExample() { + for(int k = 0; k < 4; k++) { + int forLoop1; + + for(int j = 0; j < 4; j++) { + int forLoop2; + + int ifStmt; + if (j > k) { + int thenBody; + break; + } + else if (j == k) { + int elseBody; + continue; + } + int afterIfStmt; + } + int afterForLoop2; + } + int afterForLoop1; + + int whileLoop; + int a = 10; + while(a > 0) { + int whileBody; + + int ifStmt2; + if (1) { + a--; + continue; + } + int afterIfStmt2; + a--; + } + int afterWhile; + + int doWhileLoop; + int b = 10; + do { + int whileBody; + + int ifStmt3; + if (1) { + b--; + continue; + } + int afterIfStmt3; + b--; + } while(b > 0); + int afterDoWhile; +} + +// 'switch' statements +int switchCaseExample() { + int a = 10; + + int switch1, result1; + int defaultOnly; + switch(a) { + default: + result1 = 20; + int switch1DefaultInst1; + int switch1DefaultInst2; + break; + } + int afterDefaultOnly; + int afterSwitch1; + + + int switch2, result2; + int noDefault; + switch (a) { + case 1: + result2 = 1; + int switch2Case1Inst1; + int switch2Case1Inst2; + break; + + case 3: + result2 = 3; + int switch2Case3Inst1; + int switch2Case3Inst2; + break; + + case 4 ... 8: + result2 = 48; + int switch2RangeCaseInst1; + int switch2RangeCaseInst2; + break; + } + int afterNoDefault; + int afterSwitch2; + + + int switch3, result3; + int withDefault; + switch (a) { + case 1: + result3 = 1; + int switch3Case1Inst1; + int switch3Case1Inst2; + break; + + case 3: + result3 = 3; + int switch3Case3Inst1; + int switch3Case3Inst2; + break; + + case 4 ... 8: + result3 = 48; + int switch2RangeCaseInst1; + int switch2RangeCaseInst2; + break; + + default: + result3 = 20; + int switch3DefaultInst1; + int switch3DefaultInst2; + break; + + } + int afterWithDefault; + int afterSwitch3; + + + int switch4, result4; + int intermediateDefault; + switch (a) { + case 1: + result4 = 1; + int switch4Case1Inst1; + int switch4Case1Inst2; + break; + + default: + result4 = 20; + int switch4DefaultInst1; + int switch4DefaultInst2; + break; + + case 3: + result4 = 3; + int switch4Case3Inst1; + int switch4Case3Inst2; + break; + } + int afterIntermediateDefault; + int afterSwitch4; + + + int switch5, result5; + int noBreak; + switch (a) { + case 1: + result5 = 1; + int switch5Case1Inst1; + int switch5Case1Inst2; + if (1) { + int ifBody; + break; + } + + case 2: + result5 = 2; + int switch5Case2Inst1; + int switch5Case2Inst2; + + default: + result5 = 20; + int switch5DefaultInst1; + int switch5DefaultInst2; + + case 3: + result5 = 3; + int switch5Case3Inst1; + int switch5Case3Inst2; + } + int afterNoBreak; + int afterSwitch5; + + return 0; +} + +// 'goto' and 'label' statements +int gotoAndLabelExample() { + int x = 1, y, z, result; + + if (x == 1) { + goto label1; + } else { + goto label2; + } + + label1: + y = x * 2; + z = y + 5; + goto end; + + label2: + y = x + 3; + z = y - 2; + + end: + result = y + z; + return result; +} From f4d1f370f35a1afa46123610f847060d665f2f01 Mon Sep 17 00:00:00 2001 From: Milena Gouveia Date: Mon, 14 Aug 2023 15:27:59 +0100 Subject: [PATCH 3/3] [ClavaLaraApi] Update documentation of ControlFlowGraph class --- .../src-lara-clava/clava/clava/graphs/ControlFlowGraph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js b/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js index 2dc18faa0..45eb80cb3 100644 --- a/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js +++ b/ClavaLaraApi/src-lara-clava/clava/clava/graphs/ControlFlowGraph.js @@ -34,7 +34,7 @@ class ControlFlowGraph extends Graph { * @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 = true] If true, the temporary scope statements will be kept in 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 = {}) {