diff --git a/Clava-JS/api/clava/code/Inliner.ts b/Clava-JS/api/clava/code/Inliner.ts index 1bdeb8ac5..22000853f 100644 --- a/Clava-JS/api/clava/code/Inliner.ts +++ b/Clava-JS/api/clava/code/Inliner.ts @@ -381,18 +381,35 @@ export default class Inliner { this.updateVarDecls($newNodes, newVariableMap); this.updateVarrefs($newNodes, newVariableMap, $call); this.updateVarrefsInTypes($newNodes, newVariableMap, $call); - this.renameLabels(); + this.renameLabels($newNodes, $call.getAncestor("function") as FunctionJp); } /** * Labels need to be renamed, to avoid duplicated labels. */ - private renameLabels(): void { + private renameLabels($newNodes: Scope, $destFunction: FunctionJp): void { // Maps label names to new LabelDecl const newLabels: Record = {}; + // The destination function may already contain labels generated by earlier + // inlines (e.g., from a previous Inliner instance, whose counter starts at + // zero), so generated names are checked against it instead of relying on + // the instance counter for uniqueness. + // LabelDecl join points are not traversable through Query.searchFrom, so + // existing labels are collected from the goto/label statements that + // reference them. + const destLabelNames = new Set(); + for (const jp of Query.searchFrom($destFunction, Joinpoint, { + self: ($jp: LaraJoinPoint) => + $jp instanceof GotoStmt || $jp instanceof LabelStmt, + })) { + const $jp = jp as GotoStmt | LabelStmt; + const $destLabelDecl = $jp instanceof GotoStmt ? $jp.label : $jp.decl; + destLabelNames.add($destLabelDecl.name); + } + // Visit all gotoStmt and labelStmt - for (const jp of Query.search(Joinpoint, { + for (const jp of Query.searchFrom($newNodes, Joinpoint, { self: ($jp: LaraJoinPoint) => $jp instanceof GotoStmt || $jp instanceof LabelStmt, })) { @@ -404,7 +421,11 @@ export default class Inliner { // Get new label, or create if it does not exist yet let $newLabelDecl: LabelDecl | undefined = newLabels[$labelDecl.name]; if ($newLabelDecl === undefined) { - const newLabelName = this.createNewLabelName($labelDecl.name); + let newLabelName = this.createNewLabelName($labelDecl.name); + while (destLabelNames.has(newLabelName)) { + newLabelName = this.createNewLabelName(newLabelName); + } + destLabelNames.add(newLabelName); $newLabelDecl = ClavaJoinPoints.labelDecl(newLabelName); newLabels[$labelDecl.name] = $newLabelDecl; } @@ -417,7 +438,7 @@ export default class Inliner { } // If there are any label decls, rename them - for (const $labelDecl of Query.search(LabelDecl)) { + for (const $labelDecl of Query.searchFrom($newNodes, LabelDecl)) { const $newLabelDecl = newLabels[$labelDecl.name]; $labelDecl.replaceWith($newLabelDecl); } diff --git a/ClavaWeaver/resources/clava/test/api/InlinerTest.js b/ClavaWeaver/resources/clava/test/api/InlinerTest.js index b9107cabb..966993a0e 100644 --- a/ClavaWeaver/resources/clava/test/api/InlinerTest.js +++ b/ClavaWeaver/resources/clava/test/api/InlinerTest.js @@ -132,6 +132,18 @@ new Inliner().inlineFunctionTree( console.log(Query.search("function", "callsFunctionWithLabels").first().code); +// Fresh Inliner instance per call site: label numbering must not collide with +// labels already inserted by previous instances in the same function. +const $freshCaller = Query.search("function", "callsFunctionWithLabelsFresh") + .first(); + +for (const $call of [...Query.searchFrom($freshCaller, "call")]) { + const inliner = new Inliner(); + inliner.inline($call.getAncestor("exprStmt")); +} + +console.log($freshCaller.code); + //console.log(Query.search("function", "functionWithStatic").first().ast); /* diff --git a/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.macos.txt b/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.macos.txt index d4cf4307b..9e618b27c 100644 --- a/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.macos.txt +++ b/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.macos.txt @@ -365,11 +365,11 @@ int inlineTest2() { __inline_0_decomp_8 = __inline_0_i == 0; if(__inline_0_decomp_8) { __inline_0___return_value = 1; - goto inliner_3___return_label; + goto inliner_0___return_label; } __inline_0___return_value = 2; - goto inliner_3___return_label; - inliner_3___return_label: + goto inliner_0___return_label; + inliner_0___return_label: b = __inline_0___return_value; } } @@ -383,11 +383,11 @@ int inlineTest2() { __inline_1_decomp_8 = __inline_1_i == 0; if(__inline_1_decomp_8) { __inline_1___return_value = 1; - goto inliner_0___return_label; + goto inliner_1___return_label; } __inline_1___return_value = 2; - goto inliner_0___return_label; - inliner_0___return_label: + goto inliner_1___return_label; + inliner_1___return_label: b = __inline_1___return_value; } } @@ -429,11 +429,11 @@ void functionThatCallsFunctionWithReturnButsDoesNotUseResult() { int __inline_0___return_value; if(__inline_0_a) { __inline_0___return_value = 1; - goto __return_label; + goto inliner_0___return_label; } __inline_0___return_value = 0; - goto __return_label; - __return_label: + goto inliner_0___return_label; + inliner_0___return_label: ; } } @@ -541,21 +541,46 @@ int callsFunctionWithLabels() { { int __inline_0_a; __inline_0_a = 0; - goto inliner_11_a_label; + goto inliner_0_a_label; __inline_0_a = __inline_0_a + 20; - inliner_11_a_label: + inliner_0_a_label: __inline_0_a = __inline_0_a + 10; a = __inline_0_a; } { int __inline_1_a; __inline_1_a = 0; - goto inliner_5_a_label; + goto inliner_1_a_label; __inline_1_a = __inline_1_a + 20; - inliner_5_a_label: + inliner_1_a_label: __inline_1_a = __inline_1_a + 10; a = __inline_1_a; } return a; } + +void callsFunctionWithLabelsFresh() { + int a; + a = 0; + { + int __inline_0_a; + __inline_0_a = 0; + goto inliner_0_a_label; + __inline_0_a = __inline_0_a + 20; + inliner_0_a_label: + __inline_0_a = __inline_0_a + 10; + a = __inline_0_a; + } + { + int __inline_0_a; + __inline_0_a = 0; + goto inliner_1_a_label; + __inline_0_a = __inline_0_a + 20; + inliner_1_a_label: + __inline_0_a = __inline_0_a + 10; + a = __inline_0_a; + } +} + + diff --git a/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.txt b/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.txt index 637344c96..a15ded144 100644 --- a/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.txt +++ b/ClavaWeaver/resources/clava/test/api/c/results/InlinerTest.js.txt @@ -365,11 +365,11 @@ int inlineTest2() { __inline_0_decomp_8 = __inline_0_i == 0; if(__inline_0_decomp_8) { __inline_0___return_value = 1; - goto inliner_3___return_label; + goto inliner_0___return_label; } __inline_0___return_value = 2; - goto inliner_3___return_label; - inliner_3___return_label: + goto inliner_0___return_label; + inliner_0___return_label: b = __inline_0___return_value; } } @@ -383,11 +383,11 @@ int inlineTest2() { __inline_1_decomp_8 = __inline_1_i == 0; if(__inline_1_decomp_8) { __inline_1___return_value = 1; - goto inliner_0___return_label; + goto inliner_1___return_label; } __inline_1___return_value = 2; - goto inliner_0___return_label; - inliner_0___return_label: + goto inliner_1___return_label; + inliner_1___return_label: b = __inline_1___return_value; } } @@ -429,11 +429,11 @@ void functionThatCallsFunctionWithReturnButsDoesNotUseResult() { int __inline_0___return_value; if(__inline_0_a) { __inline_0___return_value = 1; - goto __return_label; + goto inliner_0___return_label; } __inline_0___return_value = 0; - goto __return_label; - __return_label: + goto inliner_0___return_label; + inliner_0___return_label: ; } } @@ -541,21 +541,46 @@ int callsFunctionWithLabels() { { int __inline_0_a; __inline_0_a = 0; - goto inliner_11_a_label; + goto inliner_0_a_label; __inline_0_a = __inline_0_a + 20; - inliner_11_a_label: + inliner_0_a_label: __inline_0_a = __inline_0_a + 10; a = __inline_0_a; } { int __inline_1_a; __inline_1_a = 0; - goto inliner_5_a_label; + goto inliner_1_a_label; __inline_1_a = __inline_1_a + 20; - inliner_5_a_label: + inliner_1_a_label: __inline_1_a = __inline_1_a + 10; a = __inline_1_a; } return a; } + +void callsFunctionWithLabelsFresh() { + int a; + a = 0; + { + int __inline_0_a; + __inline_0_a = 0; + goto inliner_0_a_label; + __inline_0_a = __inline_0_a + 20; + inliner_0_a_label: + __inline_0_a = __inline_0_a + 10; + a = __inline_0_a; + } + { + int __inline_0_a; + __inline_0_a = 0; + goto inliner_1_a_label; + __inline_0_a = __inline_0_a + 20; + inliner_1_a_label: + __inline_0_a = __inline_0_a + 10; + a = __inline_0_a; + } +} + + diff --git a/ClavaWeaver/resources/clava/test/api/c/src/inliner.c b/ClavaWeaver/resources/clava/test/api/c/src/inliner.c index 9b68003b6..89c9af3c0 100644 --- a/ClavaWeaver/resources/clava/test/api/c/src/inliner.c +++ b/ClavaWeaver/resources/clava/test/api/c/src/inliner.c @@ -238,4 +238,11 @@ int callsFunctionWithLabels() { a = functionWithLabel(); return a; +} + +void callsFunctionWithLabelsFresh() { + int a = 0; + + a = functionWithLabel(); + a = functionWithLabel(); } \ No newline at end of file