diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 577a0f571e16ea..0a63c50d44f4b7 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1098,12 +1098,6 @@ struct CounterCoverageMappingBuilder return ExitCount; } - /// Determine whether the given condition can be constant folded. - bool ConditionFoldsToBool(const Expr *Cond) { - Expr::EvalResult Result; - return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())); - } - /// Create a Branch Region around an instrumentable condition for coverage /// and add it to the function's SourceRegions. A branch region tracks a /// "True" counter and a "False" counter for boolean expressions that @@ -1133,13 +1127,15 @@ struct CounterCoverageMappingBuilder // Alternatively, we can prevent any optimization done via // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in // CodeGenFunction.c always returns false, but that is very heavy-handed. - if (ConditionFoldsToBool(C)) - popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C), - Counter::getZero(), BranchParams)); - else - // Otherwise, create a region with the True counter and False counter. - popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, - BranchParams)); + Expr::EvalResult Result; + if (C->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())) { + if (Result.Val.getInt().getBoolValue()) + FalseCnt = Counter::getZero(); + else + TrueCnt = Counter::getZero(); + } + popRegions( + pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, BranchParams)); } } @@ -1153,12 +1149,12 @@ struct CounterCoverageMappingBuilder /// Create a Branch Region around a SwitchCase for code coverage /// and add it to the function's SourceRegions. - void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt, - Counter FalseCnt) { + void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt) { // Push region onto RegionStack but immediately pop it (which adds it to // the function's SourceRegions) because it doesn't apply to any other // source other than the SwitchCase. - popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt)); + popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), + Counter::getZero())); } /// Check whether a region with bounds \c StartLoc and \c EndLoc @@ -1870,24 +1866,16 @@ struct CounterCoverageMappingBuilder const SwitchCase *Case = S->getSwitchCaseList(); for (; Case; Case = Case->getNextSwitchCase()) { HasDefaultCase = HasDefaultCase || isa(Case); - CaseCountSum = - addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false); - createSwitchCaseRegion( - Case, getRegionCounter(Case), - subtractCounters(ParentCount, getRegionCounter(Case))); + auto CaseCount = getRegionCounter(Case); + CaseCountSum = addCounters(CaseCountSum, CaseCount, /*Simplify=*/false); + createSwitchCaseRegion(Case, CaseCount); } - // Simplify is skipped while building the counters above: it can get really - // slow on top of switches with thousands of cases. Instead, trigger - // simplification by adding zero to the last counter. - CaseCountSum = addCounters(CaseCountSum, Counter::getZero()); - // If no explicit default case exists, create a branch region to represent // the hidden branch, which will be added later by the CodeGen. This region // will be associated with the switch statement's condition. if (!HasDefaultCase) { - Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum); - Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue); - createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse); + Counter DefaultCount = subtractCounters(ParentCount, CaseCountSum); + createBranchRegion(S->getCond(), Counter::getZero(), DefaultCount); } } diff --git a/clang/test/CoverageMapping/branch-constfolded.cpp b/clang/test/CoverageMapping/branch-constfolded.cpp index 1e7e32808e8382..a2ac1c1eacd28f 100644 --- a/clang/test/CoverageMapping/branch-constfolded.cpp +++ b/clang/test/CoverageMapping/branch-constfolded.cpp @@ -5,94 +5,94 @@ // CHECK-LABEL: _Z6fand_0b: bool fand_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 - return false && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 + return false && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, (#0 - #1) } // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_1b: bool fand_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 return a && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1) -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = #2, 0 // CHECK-LABEL: _Z6fand_2bb: bool fand_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3 - return false && a && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 + return false && a && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, (#0 - #3) } // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #4, (#3 - #4) // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_3bb: bool fand_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3 return a && true && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3) -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = #4, 0 // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_4bb: bool fand_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3 return a && b && false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3) } // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = #4, (#3 - #4) - // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, 0 + // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, (#1 - #2) // CHECK-LABEL: _Z6fand_5b: bool fand_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2 - return false && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 -} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = 0, 0 + return false && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, (#0 - #1) +} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = #2, 0 // CHECK-LABEL: _Z6fand_6b: bool fand_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 - return true && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 + return true && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = #1, 0 } // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_7b: bool fand_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 return a && false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1) -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, (#1 - #2) // CHECK-LABEL: _Z5for_0b: bool for_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 - return true || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 + return true || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = (#0 - #1), 0 } // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_1b: bool for_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 return a || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1 -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, #2 // CHECK-LABEL: _Z5for_2bb: bool for_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3 - return true || a || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 + return true || a || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = (#0 - #3), 0 } // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#3 - #4), #4 // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_3bb: bool for_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3 return a || false || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3 -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, #4 // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_4bb: bool for_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3 return a || b || true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3 } // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = (#3 - #4), #4 - // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = 0, 0 + // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = (#1 - #2), 0 // CHECK-LABEL: _Z5for_5b: bool for_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2 - return true || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 -} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, 0 + return true || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = (#0 - #1), 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, #2 // CHECK-LABEL: _Z5for_6b: bool for_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 - return false || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 + return false || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, #1 } // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_7b: bool for_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 return a || true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1 -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = (#1 - #2), 0 // CHECK-LABEL: _Z5for_8b: bool for_8(bool a) { // MCDC: Decision,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:20 = M:3, C:2 - // CHECK: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = 0, 0 - // CHECK: Branch,File 0, [[@LINE+1]]:15 -> [[@LINE+1]]:20 = 0, 0 + // CHECK: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = #2, 0 + // CHECK: Branch,File 0, [[@LINE+1]]:15 -> [[@LINE+1]]:20 = 0, (#2 - #3) if (true && false) return true; else diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp index 445cdfc20e2aff..b6fd525e930f90 100644 --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -14,7 +14,7 @@ struct S { // CHECK-LABEL: _Z3foov: // CHECK-NEXT: [[@LINE+3]]:12 -> [[@LINE+8]]:2 = #0 // CHECK-NEXT: [[@LINE+3]]:15 -> [[@LINE+3]]:19 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = 0, 0 + // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = #2, 0 void foo() { // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:22 = #2 if (int j = true ? nop() // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = #2 : nop(); // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = (#0 - #2) @@ -168,7 +168,7 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = // GH-45481 S s; s.the_prop = 0? 1 : 2; // CHECK-NEXT: File 0, [[@LINE]]:16 -> [[@LINE]]:17 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:17 = 0, 0 + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:17 = 0, (#0 - #7) // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:18 -> [[@LINE-2]]:19 = #7 // CHECK-NEXT: File 0, [[@LINE-3]]:19 -> [[@LINE-3]]:20 = #7 // CHECK-NEXT: File 0, [[@LINE-4]]:23 -> [[@LINE-4]]:24 = (#0 - #7) diff --git a/clang/test/CoverageMapping/macro-expansion.c b/clang/test/CoverageMapping/macro-expansion.c index ad71fb15eda423..4cd2c934371931 100644 --- a/clang/test/CoverageMapping/macro-expansion.c +++ b/clang/test/CoverageMapping/macro-expansion.c @@ -4,29 +4,29 @@ // CHECK: File 1, [[@LINE+7]]:12 -> [[@LINE+7]]:38 = #0 // CHECK-NEXT: File 1, [[@LINE+6]]:15 -> [[@LINE+6]]:28 = (#0 + #2) // CHECK-NEXT: File 1, [[@LINE+5]]:21 -> [[@LINE+5]]:22 = (#0 + #2) -// CHECK: Branch,File 1, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = 0, 0 +// CHECK: Branch,File 1, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = 0, ((#0 + #2) - #3) // CHECK-NEXT: File 1, [[@LINE+3]]:24 -> [[@LINE+3]]:26 = #3 // CHECK-NEXT: File 1, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #2) -// CHECK-NEXT: Branch,File 1, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, 0 +// CHECK-NEXT: Branch,File 1, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, #0 #define M1 do { if (0) {} } while (0) // CHECK-NEXT: File 2, [[@LINE+12]]:15 -> [[@LINE+12]]:41 = #0 // CHECK-NEXT: File 2, [[@LINE+11]]:18 -> [[@LINE+11]]:31 = (#0 + #4) // CHECK-NEXT: File 2, [[@LINE+10]]:24 -> [[@LINE+10]]:25 = (#0 + #4) // CHECK: File 2, [[@LINE+9]]:27 -> [[@LINE+9]]:29 = #5 // CHECK-NEXT: File 2, [[@LINE+8]]:39 -> [[@LINE+8]]:40 = (#0 + #4) -// CHECK-NEXT: Branch,File 2, [[@LINE+7]]:39 -> [[@LINE+7]]:40 = 0, 0 +// CHECK-NEXT: Branch,File 2, [[@LINE+7]]:39 -> [[@LINE+7]]:40 = 0, #0 // CHECK-NEXT: File 3, [[@LINE+6]]:15 -> [[@LINE+6]]:41 = #0 // CHECK-NEXT: File 3, [[@LINE+5]]:18 -> [[@LINE+5]]:31 = (#0 + #6) // CHECK-NEXT: File 3, [[@LINE+4]]:24 -> [[@LINE+4]]:25 = (#0 + #6) // CHECK: File 3, [[@LINE+3]]:27 -> [[@LINE+3]]:29 = #7 // CHECK-NEXT: File 3, [[@LINE+2]]:39 -> [[@LINE+2]]:40 = (#0 + #6) -// CHECK-NEXT: Branch,File 3, [[@LINE+1]]:39 -> [[@LINE+1]]:40 = 0, 0 +// CHECK-NEXT: Branch,File 3, [[@LINE+1]]:39 -> [[@LINE+1]]:40 = 0, #0 #define M2(x) do { if (x) {} } while (0) // CHECK-NEXT: File 4, [[@LINE+5]]:15 -> [[@LINE+5]]:38 = #0 // CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:28 = (#0 + #8) // CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = (#0 + #8) // CHECK-NEXT: File 4, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #8) -// CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, 0 +// CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, #0 #define M3(x) do { M2(x); } while (0) // CHECK-NEXT: File 5, [[@LINE+4]]:15 -> [[@LINE+4]]:27 = #0 // CHECK-NEXT: File 5, [[@LINE+3]]:16 -> [[@LINE+3]]:19 = #0 diff --git a/clang/test/CoverageMapping/mcdc-scratch-space.c b/clang/test/CoverageMapping/mcdc-scratch-space.c index a263e9b688faed..60e456948a5182 100644 --- a/clang/test/CoverageMapping/mcdc-scratch-space.c +++ b/clang/test/CoverageMapping/mcdc-scratch-space.c @@ -3,7 +3,7 @@ // CHECK: builtin_macro0: int builtin_macro0(int a) { // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:15 = M:3, C:2 - return (__LINE__ // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:11 = 0, 0 [1,2,0] + return (__LINE__ // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:11 = #1, 0 [1,2,0] && a); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:15 = #2, (#1 - #2) [2,0,0] } @@ -11,7 +11,7 @@ int builtin_macro0(int a) { int builtin_macro1(int a) { // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:22 = M:3, C:2 return (a // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#0 - #1), #1 [1,0,2] - || __LINE__); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:14 = 0, 0 [2,0,0] + || __LINE__); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:14 = (#1 - #2), 0 [2,0,0] } #define PRE(x) pre_##x diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp index ae26ed5fe469f2..cb1c8743c36e82 100644 --- a/clang/test/CoverageMapping/mcdc-system-headers.cpp +++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp @@ -17,10 +17,10 @@ int func0(int a) { // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:3, C:2 // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1) - // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0] + // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, 0 [1,2,0] return (CONST && a); // CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) [2,0,0] - // W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = 0, 0 [1,2,0] + // W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = #1, 0 [1,2,0] } // CHECK: _Z5func1ii: diff --git a/clang/test/CoverageMapping/switch.cpp b/clang/test/CoverageMapping/switch.cpp index b47c0e80099527..a1fee644faaf0e 100644 --- a/clang/test/CoverageMapping/switch.cpp +++ b/clang/test/CoverageMapping/switch.cpp @@ -2,13 +2,13 @@ // CHECK: foo void foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+11]]:2 = #0 - switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((#0 - #2) - #3), (#2 + #3) + switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = 0, ((#0 - #2) - #3) // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+5]]:10 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = #2 - return; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + return; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+1]]:3 = 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #3 - break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 } // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = #1 int x = 0; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #1 @@ -18,24 +18,24 @@ int nop() { return 0; } // CHECK: bar void bar(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+21]]:2 = #0 - switch (i) // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = #0, 0 + switch (i) // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = 0, #0 ; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:6 = 0 switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+17]]:2 = #1 - } // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = #1, 0 + } // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = 0, #1 switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+14]]:2 = #2 - nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = #2, 0 + nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = 0, #2 // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = 0 switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+11]]:2 = #3 - case 1: // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = (#3 - #5), #5 + case 1: // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = 0, (#3 - #5) // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:10 = #5 - nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #5, (#3 - #5) + nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #5, 0 // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+7]]:2 = #4 - switch (i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#4 - #7), #7 + switch (i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = 0, (#4 - #7) nop(); // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+2]]:10 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #7 - nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, (#4 - #7) + nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, 0 } nop(); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #6 } @@ -44,7 +44,7 @@ void bar(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+21]]:2 = #0 void baz() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+5]]:2 = #0 switch (int i = true ? nop() // CHECK: [[@LINE]]:26 -> [[@LINE]]:31 = #2 : nop(); // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = (#0 - #2) - i) {} // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = #0, 0 + i) {} // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = 0, #0 nop(); // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:2 = #1 } @@ -53,35 +53,35 @@ int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+39]]:2 = #0 int i = 0; switch(i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+8]]:10 = 0 case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #2 - i = 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + i = 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 break; // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #3 - i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 break; // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #4 - break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #4, (#0 - #4) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #4, 0 } // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = #1 switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+27]]:2 = #1 case 0: // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+7]]:10 = 0 i = 1; // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:10 = #6 - break; // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #6, (#1 - #6) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #6, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:10 = #7 - i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, (#1 - #7) + i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = (#7 + #8) - break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #8, (#1 - #8) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #8, 0 } // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:3 = #5 // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+17]]:2 = #5 - switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((((#5 - #10) - #11) - #12) - #13), (((#10 + #11) + #12) + #13) + switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = 0, ((((#5 - #10) - #11) - #12) - #13) // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+8]]:11 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+7]]:11 = #10 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #10, (#5 - #10) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #10, 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:11 = (#10 + #11) - i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #11, (#5 - #11) + i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #11, 0 case 3: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = ((#10 + #11) + #12) - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #12, (#5 - #12) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #12, 0 case 4: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = (((#10 + #11) + #12) + #13) - i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #13, (#5 - #13) + i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #13, 0 } foo(1); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = #9 @@ -95,10 +95,10 @@ int pr44011(int i) { // CHECK-NEXT: File 0, [[@LINE]]:20 -> {{.*}}:2 = #0 switch (i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+6]]:13 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #2 - return 0; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + return 0; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #3 - return 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #3, (#0 - #3) + return 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #3, 0 } } // A region for counter #1 is missing due to the missing return. @@ -106,17 +106,17 @@ int pr44011(int i) { // CHECK-NEXT: File 0, [[@LINE]]:20 -> {{.*}}:2 = #0 // FIXME: End location for "case 1" shouldn't point at the end of the switch. // CHECK: fallthrough int fallthrough(int i) { // CHECK-NEXT: File 0, [[@LINE]]:24 -> [[@LINE+14]]:2 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:11 = ((((#0 - #2) - #3) - #4) - #5), (((#2 + #3) + #4) + #5) + // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:11 = 0, ((((#0 - #2) - #3) - #4) - #5) switch(i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+10]]:10 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+9]]:10 = #2 - i = 23; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + i = 23; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = (#2 + #3) - i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 break; // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0 case 3: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:10 = #4 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, 0 case 4: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = (#4 + #5) - i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #5, (#0 - #5) + i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #5, 0 break; } } @@ -126,12 +126,12 @@ void abort(void) __attribute((noreturn)); int noret(int x) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+11]]:2 switch (x) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+8]]:14 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:12 - abort(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2) + abort(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:3 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 - return 5; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + return 5; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:14 - return 10; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4) + return 10; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, 0 } } diff --git a/clang/test/CoverageMapping/switchmacro.c b/clang/test/CoverageMapping/switchmacro.c index 4c98cc7d9403a4..0696e7490cdf99 100644 --- a/clang/test/CoverageMapping/switchmacro.c +++ b/clang/test/CoverageMapping/switchmacro.c @@ -6,7 +6,7 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0 switch (i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> {{[0-9]+}}:11 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> {{[0-9]+}}:11 = #2 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, 0 if (i == 1) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = #2 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 = #3, (#2 - #3) return 0; // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3 @@ -15,7 +15,7 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0 // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3) FOO(1); case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:13 = ((#2 + #4) - #3) - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, 0 return 2; // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+4]]:3 = 0 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0 diff --git a/flang/include/flang/Optimizer/OpenMP/Passes.td b/flang/include/flang/Optimizer/OpenMP/Passes.td index 1c0ce08f5b4838..c070bc22ff20cc 100644 --- a/flang/include/flang/Optimizer/OpenMP/Passes.td +++ b/flang/include/flang/Optimizer/OpenMP/Passes.td @@ -22,6 +22,19 @@ def MapInfoFinalizationPass let dependentDialects = ["mlir::omp::OpenMPDialect"]; } +def MapsForPrivatizedSymbolsPass + : Pass<"omp-maps-for-privatized-symbols", "mlir::func::FuncOp"> { + let summary = "Creates MapInfoOp instances for privatized symbols when needed"; + let description = [{ + Adds omp.map.info operations for privatized symbols on omp.target ops + In certain situations, such as when an allocatable is privatized, its + descriptor is needed in the alloc region of the privatizer. This results + in the use of the descriptor inside the target region. As such, the + descriptor then needs to be mapped. This pass adds such MapInfoOp operations. + }]; + let dependentDialects = ["mlir::omp::OpenMPDialect"]; +} + def MarkDeclareTargetPass : Pass<"omp-mark-declare-target", "mlir::ModuleOp"> { let summary = "Marks all functions called by an OpenMP declare target function as declare target"; diff --git a/flang/lib/Optimizer/OpenMP/CMakeLists.txt b/flang/lib/Optimizer/OpenMP/CMakeLists.txt index 92051634f0378b..035d0d5ca46c76 100644 --- a/flang/lib/Optimizer/OpenMP/CMakeLists.txt +++ b/flang/lib/Optimizer/OpenMP/CMakeLists.txt @@ -2,6 +2,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) add_flang_library(FlangOpenMPTransforms FunctionFiltering.cpp + MapsForPrivatizedSymbols.cpp MapInfoFinalization.cpp MarkDeclareTarget.cpp diff --git a/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp new file mode 100644 index 00000000000000..2fa55844aec7c7 --- /dev/null +++ b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp @@ -0,0 +1,156 @@ +//===- MapsForPrivatizedSymbols.cpp +//-----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +/// \file +/// An OpenMP dialect related pass for FIR/HLFIR which creates MapInfoOp +/// instances for certain privatized symbols. +/// For example, if an allocatable variable is used in a private clause attached +/// to a omp.target op, then the allocatable variable's descriptor will be +/// needed on the device (e.g. GPU). This descriptor needs to be separately +/// mapped onto the device. This pass creates the necessary omp.map.info ops for +/// this. +//===----------------------------------------------------------------------===// +// TODO: +// 1. Before adding omp.map.info, check if we already have an omp.map.info for +// the variable in question. +// 2. Generalize this for more than just omp.target ops. +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Dialect/Support/KindMapping.h" +#include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Optimizer/OpenMP/Passes.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/Pass/Pass.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" +#include "llvm/Support/Debug.h" +#include + +#define DEBUG_TYPE "omp-maps-for-privatized-symbols" + +namespace flangomp { +#define GEN_PASS_DEF_MAPSFORPRIVATIZEDSYMBOLSPASS +#include "flang/Optimizer/OpenMP/Passes.h.inc" +} // namespace flangomp +using namespace mlir; +namespace { +class MapsForPrivatizedSymbolsPass + : public flangomp::impl::MapsForPrivatizedSymbolsPassBase< + MapsForPrivatizedSymbolsPass> { + + bool privatizerNeedsMap(omp::PrivateClauseOp &privatizer) { + Region &allocRegion = privatizer.getAllocRegion(); + Value blockArg0 = allocRegion.getArgument(0); + if (blockArg0.use_empty()) + return false; + return true; + } + omp::MapInfoOp createMapInfo(Location loc, Value var, + fir::FirOpBuilder &builder) { + uint64_t mapTypeTo = static_cast< + std::underlying_type_t>( + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO); + Operation *definingOp = var.getDefiningOp(); + auto declOp = llvm::dyn_cast_or_null(definingOp); + assert(declOp && + "Expected defining Op of privatized var to be hlfir.declare"); + + // We want the first result of the hlfir.declare op because our goal + // is to map the descriptor (fir.box or fir.boxchar) and the first + // result for hlfir.declare is the descriptor if a the symbol being + // decalred needs a descriptor. + Value varPtr = declOp.getBase(); + + // If we do not have a reference to descritor, but the descriptor itself + // then we need to store that on the stack so that we can map the + // address of the descriptor. + if (mlir::isa(varPtr.getType()) || + mlir::isa(varPtr.getType())) { + OpBuilder::InsertPoint savedInsPoint = builder.saveInsertionPoint(); + mlir::Block *allocaBlock = builder.getAllocaBlock(); + assert(allocaBlock && "No allocablock found for a funcOp"); + builder.setInsertionPointToStart(allocaBlock); + auto alloca = builder.create(loc, varPtr.getType()); + builder.restoreInsertionPoint(savedInsPoint); + builder.create(loc, varPtr, alloca); + varPtr = alloca; + } + return builder.create( + loc, varPtr.getType(), varPtr, + TypeAttr::get(llvm::cast(varPtr.getType()) + .getElementType()), + /*varPtrPtr=*/Value{}, + /*members=*/SmallVector{}, + /*member_index=*/DenseIntElementsAttr{}, + /*bounds=*/ValueRange{}, + builder.getIntegerAttr(builder.getIntegerType(64, /*isSigned=*/false), + mapTypeTo), + builder.getAttr( + omp::VariableCaptureKind::ByRef), + StringAttr(), builder.getBoolAttr(false)); + } + void addMapInfoOp(omp::TargetOp targetOp, omp::MapInfoOp mapInfoOp) { + auto argIface = llvm::cast(*targetOp); + unsigned insertIndex = + argIface.getMapBlockArgsStart() + argIface.numMapBlockArgs(); + targetOp.getMapVarsMutable().append(ValueRange{mapInfoOp}); + targetOp.getRegion().insertArgument(insertIndex, mapInfoOp.getType(), + mapInfoOp.getLoc()); + } + void addMapInfoOps(omp::TargetOp targetOp, + llvm::SmallVectorImpl &mapInfoOps) { + for (auto mapInfoOp : mapInfoOps) + addMapInfoOp(targetOp, mapInfoOp); + } + void runOnOperation() override { + ModuleOp module = getOperation()->getParentOfType(); + fir::KindMapping kindMap = fir::getKindMapping(module); + fir::FirOpBuilder builder{module, std::move(kindMap)}; + llvm::DenseMap> + mapInfoOpsForTarget; + + getOperation()->walk([&](omp::TargetOp targetOp) { + if (targetOp.getPrivateVars().empty()) + return; + OperandRange privVars = targetOp.getPrivateVars(); + std::optional privSyms = targetOp.getPrivateSyms(); + SmallVector mapInfoOps; + for (auto [privVar, privSym] : llvm::zip_equal(privVars, *privSyms)) { + + SymbolRefAttr privatizerName = llvm::cast(privSym); + omp::PrivateClauseOp privatizer = + SymbolTable::lookupNearestSymbolFrom( + targetOp, privatizerName); + if (!privatizerNeedsMap(privatizer)) { + continue; + } + builder.setInsertionPoint(targetOp); + Location loc = targetOp.getLoc(); + omp::MapInfoOp mapInfoOp = createMapInfo(loc, privVar, builder); + mapInfoOps.push_back(mapInfoOp); + LLVM_DEBUG(llvm::dbgs() << "MapsForPrivatizedSymbolsPass created ->\n"); + LLVM_DEBUG(mapInfoOp.dump()); + } + if (!mapInfoOps.empty()) { + mapInfoOpsForTarget.insert({targetOp.getOperation(), mapInfoOps}); + } + }); + if (!mapInfoOpsForTarget.empty()) { + for (auto &[targetOp, mapInfoOps] : mapInfoOpsForTarget) { + addMapInfoOps(static_cast(targetOp), mapInfoOps); + } + } + } +}; +} // namespace diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 3fa5c54403bd8c..3c139f7e93405c 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -243,6 +243,7 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, /// rather than the host device. void createOpenMPFIRPassPipeline(mlir::PassManager &pm, bool isTargetDevice) { pm.addPass(flangomp::createMapInfoFinalizationPass()); + pm.addPass(flangomp::createMapsForPrivatizedSymbolsPass()); pm.addPass(flangomp::createMarkDeclareTargetPass()); if (isTargetDevice) pm.addPass(flangomp::createFunctionFilteringPass()); diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 index a27de1152ce17a..e11525c569ffb8 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 @@ -18,22 +18,22 @@ end subroutine target_allocatable ! CHECK-SAME: @[[VAR_PRIVATIZER_SYM:.*]] : ! CHECK-SAME: [[TYPE:!fir.ref>>]] alloc { ! CHECK: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]): -! CHECK: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box> {bindc_name = "alloc_var", {{.*}}} +! CHECK: %[[PRIV_ALLOC:.*]] = fir.alloca [[DESC_TYPE:!fir.box>]] {bindc_name = "alloc_var", {{.*}}} -! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : !fir.ref>> -! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]] : (!fir.box>) -> !fir.heap +! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : [[TYPE]] +! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]] : ([[DESC_TYPE]]) -> !fir.heap ! CHECK-NEXT: %[[PRIV_ARG_ADDR:.*]] = fir.convert %[[PRIV_ARG_BOX]] : (!fir.heap) -> i64 ! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64 ! CHECK-NEXT: %[[ALLOC_COND:.*]] = arith.cmpi ne, %[[PRIV_ARG_ADDR]], %[[C0]] : i64 ! CHECK-NEXT: fir.if %[[ALLOC_COND]] { ! CHECK: %[[PRIV_ALLOCMEM:.*]] = fir.allocmem i32 {fir.must_be_heap = true, {{.*}}} -! CHECK-NEXT: %[[PRIV_ALLOCMEM_BOX:.*]] = fir.embox %[[PRIV_ALLOCMEM]] : (!fir.heap) -> !fir.box> -! CHECK-NEXT: fir.store %[[PRIV_ALLOCMEM_BOX]] to %[[PRIV_ALLOC]] : !fir.ref>> +! CHECK-NEXT: %[[PRIV_ALLOCMEM_BOX:.*]] = fir.embox %[[PRIV_ALLOCMEM]] : (!fir.heap) -> [[DESC_TYPE]] +! CHECK-NEXT: fir.store %[[PRIV_ALLOCMEM_BOX]] to %[[PRIV_ALLOC]] : [[TYPE]] ! CHECK-NEXT: } else { ! CHECK-NEXT: %[[ZERO_BITS:.*]] = fir.zero_bits !fir.heap -! CHECK-NEXT: %[[ZERO_BOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap) -> !fir.box> -! CHECK-NEXT: fir.store %[[ZERO_BOX]] to %[[PRIV_ALLOC]] : !fir.ref>> +! CHECK-NEXT: %[[ZERO_BOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap) -> [[DESC_TYPE]] +! CHECK-NEXT: fir.store %[[ZERO_BOX]] to %[[PRIV_ALLOC]] : [[TYPE]] ! CHECK-NEXT: } ! CHECK-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOC]] @@ -63,9 +63,11 @@ end subroutine target_allocatable ! CHECK-LABEL: func.func @_QPtarget_allocatable() { -! CHECK: %[[VAR_ALLOC:.*]] = fir.alloca !fir.box> +! CHECK: %[[VAR_ALLOC:.*]] = fir.alloca [[DESC_TYPE]] ! CHECK-SAME: {bindc_name = "alloc_var", {{.*}}} ! CHECK: %[[VAR_DECL:.*]]:2 = hlfir.declare %[[VAR_ALLOC]] -! CHECK: omp.target private( +! CHECK: %[[MAP_VAR:.*]] = omp.map.info var_ptr(%[[VAR_DECL]]#0 : [[TYPE]], [[DESC_TYPE]]) +! CHECK-SAME: map_clauses(to) capture(ByRef) -> [[TYPE]] +! CHECK: omp.target map_entries(%[[MAP_VAR]] -> %arg0 : [[TYPE]]) private( ! CHECK-SAME: @[[VAR_PRIVATIZER_SYM]] %[[VAR_DECL]]#0 -> %{{.*}} : [[TYPE]]) { diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 index ce98f518581a45..b0c76ff3845f83 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 @@ -147,12 +147,29 @@ end subroutine target_allocatable ! CHECK-NEXT: } ! CHECK: func.func @_QPtarget_allocatable +! CHECK: %[[CHAR_VAR_DESC_ALLOCA:.*]] = fir.alloca !fir.boxchar<1> +! CHECK: %[[REAL_ARR_DESC_ALLOCA:.*]] = fir.alloca !fir.box> +! CHECK: %[[ALLOC_VAR_ALLOCA:.*]] = fir.alloca !fir.box> {bindc_name = "alloc_var", {{.*}}} +! CHECK: %[[ALLOC_VAR_DECL:.*]]:2 = hlfir.declare %[[ALLOC_VAR_ALLOCA]] ! CHECK: %[[MAPPED_ALLOC:.*]] = fir.alloca i32 {bindc_name = "mapped_var", {{.*}}} ! CHECK-NEXT: %[[MAPPED_DECL:.*]]:2 = hlfir.declare %[[MAPPED_ALLOC]] -! CHECK: %[[MAPPED_MI:.*]] = omp.map.info var_ptr(%[[MAPPED_DECL]]#1 : !fir.ref, i32) - +! CHECK: %[[CHAR_VAR_ALLOC:.*]] = fir.alloca !fir.char<1,?>{{.*}} {bindc_name = "char_var", {{.*}}} +! CHECK: %[[CHAR_VAR_DECL:.*]]:2 = hlfir.declare %[[CHAR_VAR_ALLOC]] typeparams +! CHECK: %[[REAL_ARR_ALLOC:.*]] = fir.alloca !fir.array, {{.*}} {bindc_name = "real_arr", {{.*}}} +! CHECK: %[[REAL_ARR_DECL:.*]]:2 = hlfir.declare %[[REAL_ARR_ALLOC]]({{.*}}) +! CHECK: %[[MAPPED_MI0:.*]] = omp.map.info var_ptr(%[[MAPPED_DECL]]#1 : !fir.ref, i32) {{.*}} +! CHECK: %[[ALLOC_VAR_MAP:.*]] = omp.map.info var_ptr(%[[ALLOC_VAR_DECL]]#0 : !fir.ref>>, !fir.box>) +! CHECK: fir.store %[[REAL_ARR_DECL]]#0 to %[[REAL_ARR_DESC_ALLOCA]] : !fir.ref>> +! CHECK: %[[REAL_ARR_DESC_MAP:.*]] = omp.map.info var_ptr(%[[REAL_ARR_DESC_ALLOCA]] : !fir.ref>>, !fir.box>) +! CHECK: fir.store %[[CHAR_VAR_DECL]]#0 to %[[CHAR_VAR_DESC_ALLOCA]] : !fir.ref> +! CHECK: %[[CHAR_VAR_DESC_MAP:.*]] = omp.map.info var_ptr(%[[CHAR_VAR_DESC_ALLOCA]] : !fir.ref>, !fir.boxchar<1>) ! CHECK: omp.target -! CHECK-SAME: map_entries(%[[MAPPED_MI]] -> %[[MAPPED_ARG:.*]] : !fir.ref) +! CHECK-SAME: map_entries( +! CHECK-SAME: %[[MAPPED_MI0]] -> %[[MAPPED_ARG0:[^,]+]], +! CHECK-SAME: %[[ALLOC_VAR_MAP]] -> %[[MAPPED_ARG1:[^,]+]] +! CHECK-SAME %[[REAL_ARR_DESC_MAP]] -> %[[MAPPED_ARG2:[^,]+]] +! CHECK_SAME %[[CHAR_VAR_DESC_MAP]] -> %[[MAPPED_ARG3:.[^,]+]] : +! CHECK-SAME !fir.ref, !fir.ref>>, !fir.ref>>, !fir.ref>) ! CHECK-SAME: private( ! CHECK-SAME: @[[ALLOC_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[ALLOC_ARG:[^,]+]], ! CHECK-SAME: @[[REAL_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[REAL_ARG:[^,]+]], @@ -162,7 +179,6 @@ end subroutine target_allocatable ! CHECK-SAME: @[[CHAR_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[CHAR_ARG:[^,]+]] : ! CHECK-SAME: !fir.ref>>, !fir.ref, !fir.ref, !fir.box>, !fir.ref>, !fir.boxchar<1>) { ! CHECK-NOT: fir.alloca -! CHECK: hlfir.declare %[[MAPPED_ARG]] ! CHECK: hlfir.declare %[[ALLOC_ARG]] ! CHECK: hlfir.declare %[[REAL_ARG]] ! CHECK: hlfir.declare %[[LB_ARG]] diff --git a/flang/test/Transforms/omp-maps-for-privatized-symbols.fir b/flang/test/Transforms/omp-maps-for-privatized-symbols.fir new file mode 100644 index 00000000000000..d32444aaabf237 --- /dev/null +++ b/flang/test/Transforms/omp-maps-for-privatized-symbols.fir @@ -0,0 +1,48 @@ +// RUN: fir-opt --split-input-file --omp-maps-for-privatized-symbols %s | FileCheck %s +module attributes {omp.is_target_device = false} { + omp.private {type = private} @_QFtarget_simpleEsimple_var_private_ref_box_heap_i32 : !fir.ref>> alloc { + ^bb0(%arg0: !fir.ref>>): + %0 = fir.alloca !fir.box> {bindc_name = "simple_var", pinned, uniq_name = "_QFtarget_simpleEsimple_var"} + %1 = fir.load %arg0 : !fir.ref>> + %5:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + omp.yield(%5#0 : !fir.ref>>) + } + func.func @_QPtarget_simple() { + %0 = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFtarget_simpleEa"} + %1:2 = hlfir.declare %0 {uniq_name = "_QFtarget_simpleEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %2 = fir.alloca !fir.box> {bindc_name = "simple_var", uniq_name = "_QFtarget_simpleEsimple_var"} + %3 = fir.zero_bits !fir.heap + %4 = fir.embox %3 : (!fir.heap) -> !fir.box> + fir.store %4 to %2 : !fir.ref>> + %5:2 = hlfir.declare %2 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + %c2_i32 = arith.constant 2 : i32 + hlfir.assign %c2_i32 to %1#0 : i32, !fir.ref + %6 = omp.map.info var_ptr(%1#1 : !fir.ref, i32) map_clauses(to) capture(ByRef) -> !fir.ref {name = "a"} + omp.target map_entries(%6 -> %arg0 : !fir.ref) private(@_QFtarget_simpleEsimple_var_private_ref_box_heap_i32 %5#0 -> %arg1 : !fir.ref>>) { + %11:2 = hlfir.declare %arg0 {uniq_name = "_QFtarget_simpleEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %12:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + %c10_i32 = arith.constant 10 : i32 + %13 = fir.load %11#0 : !fir.ref + %14 = arith.addi %c10_i32, %13 : i32 + hlfir.assign %14 to %12#0 realloc : i32, !fir.ref>> + omp.terminator + } + %7 = fir.load %5#1 : !fir.ref>> + %8 = fir.box_addr %7 : (!fir.box>) -> !fir.heap + %9 = fir.convert %8 : (!fir.heap) -> i64 + %c0_i64 = arith.constant 0 : i64 + %10 = arith.cmpi ne, %9, %c0_i64 : i64 + fir.if %10 { + %11 = fir.load %5#1 : !fir.ref>> + %12 = fir.box_addr %11 : (!fir.box>) -> !fir.heap + fir.freemem %12 : !fir.heap + %13 = fir.zero_bits !fir.heap + %14 = fir.embox %13 : (!fir.heap) -> !fir.box> + fir.store %14 to %5#1 : !fir.ref>> + } + return + } +} +// CHECK: %[[MAP0:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref, i32) map_clauses(to) capture(ByRef) -> !fir.ref {name = "a"} +// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) -> !fir.ref>> +// CHECK: omp.target map_entries(%[[MAP0]] -> %arg0, %[[MAP1]] -> %arg1 : !fir.ref, !fir.ref>>) diff --git a/libc/newhdrgen/yaml/math.yaml b/libc/newhdrgen/yaml/math.yaml index 98ea1a0d25fbb7..fe07803cff06f8 100644 --- a/libc/newhdrgen/yaml/math.yaml +++ b/libc/newhdrgen/yaml/math.yaml @@ -206,6 +206,13 @@ functions: return_type: float arguments: - type: float + - name: coshf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: ddivl standards: - stdc @@ -266,6 +273,13 @@ functions: return_type: float arguments: - type: float + - name: exp10m1f16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: exp2 standards: - stdc @@ -1557,6 +1571,13 @@ functions: return_type: float arguments: - type: float + - name: log10f16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: log1p standards: - stdc @@ -1581,6 +1602,13 @@ functions: return_type: float arguments: - type: float + - name: log2f16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: logb standards: - stdc @@ -1619,6 +1647,13 @@ functions: return_type: float arguments: - type: float + - name: logf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: lrint standards: - stdc @@ -2297,6 +2332,13 @@ functions: return_type: float arguments: - type: float + - name: sinhf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: sinpif16 standards: - stdc @@ -2323,6 +2365,13 @@ functions: arguments: - type: float128 guard: LIBC_TYPES_HAS_FLOAT128 + - name: sqrtf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: sqrtl standards: - stdc @@ -2347,6 +2396,13 @@ functions: return_type: float arguments: - type: float + - name: tanhf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: totalorder standards: - stdc diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 2a3aba28fb6ca5..32e6fb43d988ff 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -2150,9 +2150,9 @@ bool UnwindCursor::getInfoFromTBTable(pint_t pc, R ®isters) { dlsym(libHandle, "__xlcxx_personality_v0")); if (xlcPersonalityV0 == NULL) { _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno); + dlclose(libHandle); assert(0 && "dlsym() failed"); } - dlclose(libHandle); errno = saveErrno; } xlcPersonalityV0InitLock.unlock(); diff --git a/lld/ELF/AArch64ErrataFix.cpp b/lld/ELF/AArch64ErrataFix.cpp index cd8fbf16f5b839..f9e03ce5bbe4db 100644 --- a/lld/ELF/AArch64ErrataFix.cpp +++ b/lld/ELF/AArch64ErrataFix.cpp @@ -417,7 +417,7 @@ void Patch843419Section::writeTo(uint8_t *buf) { // Return address is the next instruction after the one we have just copied. uint64_t s = getLDSTAddr() + 4; - uint64_t p = patchSym->getVA() + 4; + uint64_t p = patchSym->getVA(ctx) + 4; ctx.target->relocateNoSym(buf + 4, R_AARCH64_JUMP26, s - p); } diff --git a/lld/ELF/ARMErrataFix.cpp b/lld/ELF/ARMErrataFix.cpp index 630084afd509ce..6d759d7dec1d8a 100644 --- a/lld/ELF/ARMErrataFix.cpp +++ b/lld/ELF/ARMErrataFix.cpp @@ -218,7 +218,7 @@ static bool branchDestInFirstRegion(Ctx &ctx, const InputSection *isec, // or the PLT. if (r) { uint64_t dst = - (r->expr == R_PLT_PC) ? r->sym->getPltVA(ctx) : r->sym->getVA(); + r->expr == R_PLT_PC ? r->sym->getPltVA(ctx) : r->sym->getVA(ctx); // Account for Thumb PC bias, usually cancelled to 0 by addend of -4. destAddr = dst + r->addend + 4; } else { @@ -449,7 +449,7 @@ static void implementPatch(ScanResult sr, InputSection *isec, // Thunk from the patch to the target. uint64_t dstSymAddr = (sr.rel->expr == R_PLT_PC) ? sr.rel->sym->getPltVA(ctx) - : sr.rel->sym->getVA(); + : sr.rel->sym->getVA(ctx); destIsARM = (dstSymAddr & 1) == 0; } psec = make(ctx, isec, sr.off, sr.instr, destIsARM); diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 260307ac4c3dcb..f4f867d019136e 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -360,7 +360,7 @@ void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const { void AArch64::writeIgotPlt(uint8_t *buf, const Symbol &s) const { if (ctx.arg.writeAddends) - write64(ctx, buf, s.getVA()); + write64(ctx, buf, s.getVA(ctx)); } void AArch64::writePltHeader(uint8_t *buf) const { @@ -416,7 +416,7 @@ bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file, if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26 && type != R_AARCH64_PLT32) return false; - uint64_t dst = expr == R_PLT_PC ? s.getPltVA(ctx) : s.getVA(a); + uint64_t dst = expr == R_PLT_PC ? s.getPltVA(ctx) : s.getVA(ctx, a); return !inBranchRange(type, branchAddr, dst); } @@ -808,7 +808,7 @@ bool AArch64Relaxer::tryRelaxAdrpAdd(const Relocation &adrpRel, Symbol &sym = *adrpRel.sym; // Check if the address difference is within 1MiB range. - int64_t val = sym.getVA() - (secAddr + addRel.offset); + int64_t val = sym.getVA(ctx) - (secAddr + addRel.offset); if (val < -1024 * 1024 || val >= 1024 * 1024) return false; @@ -874,7 +874,7 @@ bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel, return false; // Check if the address difference is within 4GB range. int64_t val = - getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset); + getAArch64Page(sym.getVA(ctx)) - getAArch64Page(secAddr + adrpRel.offset); if (val != llvm::SignExtend64(val, 33)) return false; @@ -890,11 +890,11 @@ bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel, ctx.target->relocate( buf + adrpSymRel.offset, adrpSymRel, - SignExtend64(getAArch64Page(sym.getVA()) - + SignExtend64(getAArch64Page(sym.getVA(ctx)) - getAArch64Page(secAddr + adrpSymRel.offset), 64)); ctx.target->relocate(buf + addRel.offset, addRel, - SignExtend64(sym.getVA(), 64)); + SignExtend64(sym.getVA(ctx), 64)); tryRelaxAdrpAdd(adrpSymRel, addRel, secAddr, buf); return true; } diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index 9bb3604ce61cc5..be3f80337aae71 100644 --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -213,7 +213,7 @@ void ARM::writeGotPlt(uint8_t *buf, const Symbol &) const { void ARM::writeIgotPlt(uint8_t *buf, const Symbol &s) const { // An ARM entry is the address of the ifunc resolver function. - write32(ctx, buf, s.getVA()); + write32(ctx, buf, s.getVA(ctx)); } // Long form PLT Header that does not have any restrictions on the displacement @@ -404,26 +404,26 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file, // Otherwise we need to interwork if STT_FUNC Symbol has bit 0 set (Thumb). assert(!useThumbPLTs(ctx) && "If the source is ARM, we should not need Thumb PLTs"); - if (s.isFunc() && expr == R_PC && (s.getVA() & 1)) + if (s.isFunc() && expr == R_PC && (s.getVA(ctx) & 1)) return true; [[fallthrough]]; case R_ARM_CALL: { - uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA(ctx) : s.getVA(); + uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA(ctx) : s.getVA(ctx); return !inBranchRange(type, branchAddr, dst + a) || - (!ctx.arg.armHasBlx && (s.getVA() & 1)); + (!ctx.arg.armHasBlx && (s.getVA(ctx) & 1)); } case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: // Source is Thumb, when all PLT entries are ARM interworking is required. // Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM). if ((expr == R_PLT_PC && !useThumbPLTs(ctx)) || - (s.isFunc() && (s.getVA() & 1) == 0)) + (s.isFunc() && (s.getVA(ctx) & 1) == 0)) return true; [[fallthrough]]; case R_ARM_THM_CALL: { - uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA(ctx) : s.getVA(); + uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA(ctx) : s.getVA(ctx); return !inBranchRange(type, branchAddr, dst + a) || - (!ctx.arg.armHasBlx && (s.getVA() & 1) == 0);; + (!ctx.arg.armHasBlx && (s.getVA(ctx) & 1) == 0); } } return false; @@ -1399,7 +1399,7 @@ void ArmCmseSGSection::writeTo(uint8_t *buf) { write16(ctx, p + 4, 0xf000); // B.W S write16(ctx, p + 6, 0xb000); ctx.target->relocateNoSym(p + 4, R_ARM_THM_JUMP24, - s->acleSeSym->getVA() - + s->acleSeSym->getVA(ctx) - (getVA() + s->offset + s->size)); } } @@ -1439,8 +1439,8 @@ void ArmCmseSGSection::finalizeContents() { for (size_t i = 0; i < sgVeneers.size(); ++i) { ArmCmseSGVeneer *s = sgVeneers[i]; s->offset = i * s->size; - Defined(file, StringRef(), s->sym->binding, s->sym->stOther, s->sym->type, - s->offset | 1, s->size, this) + Defined(ctx, file, StringRef(), s->sym->binding, s->sym->stOther, + s->sym->type, s->offset | 1, s->size, this) .overwrite(*s->sym); } } @@ -1466,16 +1466,15 @@ template void elf::writeARMCmseImportLib(Ctx &ctx) { osIsPairs.emplace_back(make(ctx, shstrtab->name, 0, 0), shstrtab); - std::sort(ctx.symtab->cmseSymMap.begin(), ctx.symtab->cmseSymMap.end(), - [](const auto &a, const auto &b) -> bool { - return a.second.sym->getVA() < b.second.sym->getVA(); - }); + llvm::sort(ctx.symtab->cmseSymMap, [&](const auto &a, const auto &b) { + return a.second.sym->getVA(ctx) < b.second.sym->getVA(ctx); + }); // Copy the secure gateway entry symbols to the import library symbol table. for (auto &p : ctx.symtab->cmseSymMap) { Defined *d = cast(p.second.sym); impSymTab->addSymbol(makeDefined( - ctx.internalFile, d->getName(), d->computeBinding(ctx), - /*stOther=*/0, STT_FUNC, d->getVA(), d->getSize(), nullptr)); + ctx, ctx.internalFile, d->getName(), d->computeBinding(ctx), + /*stOther=*/0, STT_FUNC, d->getVA(ctx), d->getSize(), nullptr)); } size_t idx = 0; diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp index 4dc605c47059c1..64790f1ce83ab3 100644 --- a/lld/ELF/Arch/AVR.cpp +++ b/lld/ELF/Arch/AVR.cpp @@ -110,7 +110,7 @@ bool AVR::needsThunk(RelExpr expr, RelType type, const InputFile *file, case R_AVR_HI8_LDI_GS: // A thunk is needed if the symbol's virtual address is out of range // [0, 0x1ffff]. - return s.getVA() >= 0x20000; + return s.getVA(ctx) >= 0x20000; default: return false; } diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp index 5923cda2298b4e..876aadcb91511b 100644 --- a/lld/ELF/Arch/LoongArch.cpp +++ b/lld/ELF/Arch/LoongArch.cpp @@ -316,9 +316,9 @@ void LoongArch::writeGotPlt(uint8_t *buf, const Symbol &s) const { void LoongArch::writeIgotPlt(uint8_t *buf, const Symbol &s) const { if (ctx.arg.writeAddends) { if (ctx.arg.is64) - write64le(buf, s.getVA()); + write64le(buf, s.getVA(ctx)); else - write32le(buf, s.getVA()); + write32le(buf, s.getVA(ctx)); } } diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index 1d3000793ca268..d84e85239d2ec2 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -96,7 +96,7 @@ RelExpr MIPS::getRelExpr(RelType type, const Symbol &s, // If the target symbol is not preemptible and is not microMIPS, // it might be possible to replace jalr/jr instruction by bal/b. // It depends on the target symbol's offset. - if (!s.isPreemptible && !(s.getVA() & 0x1)) + if (!s.isPreemptible && !(s.getVA(ctx) & 0x1)) return R_PC; return R_NONE; case R_MICROMIPS_JALR: diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index 3af4101fff606f..2cd526020f7d35 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -209,7 +209,7 @@ bool PPC::needsThunk(RelExpr expr, RelType type, const InputFile *file, return true; if (s.isUndefWeak()) return false; - return !PPC::inBranchRange(type, branchAddr, s.getVA(a)); + return !PPC::inBranchRange(type, branchAddr, s.getVA(ctx, a)); } uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; } diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index d937492fe440d7..d0f59681ccbd3c 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -254,7 +254,7 @@ static bool addOptional(Ctx &ctx, StringRef name, uint64_t value, Symbol *sym = ctx.symtab->find(name); if (!sym || sym->isDefined()) return false; - sym->resolve(ctx, Defined{ctx.internalFile, StringRef(), STB_GLOBAL, + sym->resolve(ctx, Defined{ctx, ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, STT_FUNC, value, /*size=*/0, /*section=*/nullptr}); defined.push_back(cast(sym)); @@ -404,7 +404,7 @@ static bool tryRelaxPPC64TocIndirection(Ctx &ctx, const Relocation &rel, assert(!d->isGnuIFunc()); // Two instructions can materialize a 32-bit signed offset from the toc base. - uint64_t tocRelative = d->getVA(addend) - getPPC64TocBase(ctx); + uint64_t tocRelative = d->getVA(ctx, addend) - getPPC64TocBase(ctx); if (!isInt<32>(tocRelative)) return false; @@ -1452,7 +1452,7 @@ bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file, // a range-extending thunk. // See the comment in getRelocTargetVA() about R_PPC64_CALL. return !inBranchRange(type, branchAddr, - s.getVA(a) + + s.getVA(ctx, a) + getPPC64GlobalEntryToLocalEntryOffset(s.stOther)); } diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 1ae016e4de01ee..e80dfbd4351b1e 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -214,9 +214,9 @@ void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const { void RISCV::writeIgotPlt(uint8_t *buf, const Symbol &s) const { if (ctx.arg.writeAddends) { if (ctx.arg.is64) - write64le(buf, s.getVA()); + write64le(buf, s.getVA(ctx)); else - write32le(buf, s.getVA()); + write32le(buf, s.getVA(ctx)); } } @@ -466,7 +466,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { case INTERNAL_R_RISCV_GPREL_I: case INTERNAL_R_RISCV_GPREL_S: { Defined *gp = ctx.sym.riscvGlobalPointer; - int64_t displace = SignExtend64(val - gp->getVA(), bits); + int64_t displace = SignExtend64(val - gp->getVA(ctx), bits); checkInt(ctx, loc, displace, 12, rel); uint32_t insn = (read32le(loc) & ~(31 << 15)) | (X_GP << 15); if (rel.type == INTERNAL_R_RISCV_GPREL_I) @@ -657,7 +657,8 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { const Relocation &rel1 = relocs[i + 1]; if (rel.type == R_RISCV_SET_ULEB128 && rel1.type == R_RISCV_SUB_ULEB128 && rel.offset == rel1.offset) { - auto val = rel.sym->getVA(rel.addend) - rel1.sym->getVA(rel1.addend); + auto val = rel.sym->getVA(ctx, rel.addend) - + rel1.sym->getVA(ctx, rel1.addend); if (overwriteULEB128(loc, val) >= 0x80) errorOrWarn(sec.getLocation(rel.offset) + ": ULEB128 value " + Twine(val) + " exceeds available space; references '" + @@ -737,7 +738,7 @@ static void relaxCall(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc, const uint64_t insnPair = read64le(sec.content().data() + r.offset); const uint32_t rd = extractBits(insnPair, 32 + 11, 32 + 7); const uint64_t dest = - (r.expr == R_PLT_PC ? sym.getPltVA(ctx) : sym.getVA()) + r.addend; + (r.expr == R_PLT_PC ? sym.getPltVA(ctx) : sym.getVA(ctx)) + r.addend; const int64_t displace = dest - loc; if (rvc && isInt<12>(displace) && rd == 0) { @@ -757,9 +758,9 @@ static void relaxCall(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc, } // Relax local-exec TLS when hi20 is zero. -static void relaxTlsLe(const InputSection &sec, size_t i, uint64_t loc, - Relocation &r, uint32_t &remove) { - uint64_t val = r.sym->getVA(r.addend); +static void relaxTlsLe(Ctx &ctx, const InputSection &sec, size_t i, + uint64_t loc, Relocation &r, uint32_t &remove) { + uint64_t val = r.sym->getVA(ctx, r.addend); if (hi20(val) != 0) return; uint32_t insn = read32le(sec.content().data() + r.offset); @@ -791,7 +792,7 @@ static void relaxHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i, if (!gp) return; - if (!isInt<12>(r.sym->getVA(r.addend) - gp->getVA())) + if (!isInt<12>(r.sym->getVA(ctx, r.addend) - gp->getVA(ctx))) return; switch (r.type) { @@ -851,7 +852,7 @@ static bool relax(Ctx &ctx, InputSection &sec) { case R_RISCV_TPREL_LO12_I: case R_RISCV_TPREL_LO12_S: if (relaxable(relocs, i)) - relaxTlsLe(sec, i, loc, r, remove); + relaxTlsLe(ctx, sec, i, loc, r, remove); break; case R_RISCV_HI20: case R_RISCV_LO12_I: @@ -863,7 +864,7 @@ static bool relax(Ctx &ctx, InputSection &sec) { // For TLSDESC=>LE, we can use the short form if hi20 is zero. tlsdescRelax = relaxable(relocs, i); toLeShortForm = tlsdescRelax && r.expr == R_RELAX_TLS_GD_TO_LE && - !hi20(r.sym->getVA(r.addend)); + !hi20(r.sym->getVA(ctx, r.addend)); [[fallthrough]]; case R_RISCV_TLSDESC_LOAD_LO12: // For TLSDESC=>LE/IE, AUIPC and L[DW] are removed if relaxable. diff --git a/lld/ELF/Arch/SystemZ.cpp b/lld/ELF/Arch/SystemZ.cpp index 584379638ad981..106b530c31b28b 100644 --- a/lld/ELF/Arch/SystemZ.cpp +++ b/lld/ELF/Arch/SystemZ.cpp @@ -188,7 +188,7 @@ void SystemZ::writeGotPlt(uint8_t *buf, const Symbol &s) const { void SystemZ::writeIgotPlt(uint8_t *buf, const Symbol &s) const { if (ctx.arg.writeAddends) - write64be(buf, s.getVA()); + write64be(buf, s.getVA(ctx)); } void SystemZ::writePltHeader(uint8_t *buf) const { diff --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp index 58199cdb99a284..a36212a5b1690a 100644 --- a/lld/ELF/Arch/X86.cpp +++ b/lld/ELF/Arch/X86.cpp @@ -181,7 +181,7 @@ void X86::writeGotPlt(uint8_t *buf, const Symbol &s) const { void X86::writeIgotPlt(uint8_t *buf, const Symbol &s) const { // An x86 entry is the address of the ifunc resolver function. - write32le(buf, s.getVA()); + write32le(buf, s.getVA(ctx)); } RelType X86::getDynRel(RelType type) const { diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index df2983f2022818..d32ba638b740c5 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -429,7 +429,7 @@ void X86_64::writeGotPlt(uint8_t *buf, const Symbol &s) const { void X86_64::writeIgotPlt(uint8_t *buf, const Symbol &s) const { // An x86 entry is the address of the ifunc resolver function (for -z rel). if (ctx.arg.writeAddends) - write64le(buf, s.getVA()); + write64le(buf, s.getVA(ctx)); } void X86_64::writePltHeader(uint8_t *buf) const { diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 913c6ccf371cc7..de245fb3096956 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2388,7 +2388,7 @@ static void replaceCommonSymbols(Ctx &ctx) { auto *bss = make(ctx, "COMMON", s->size, s->alignment); bss->file = s->file; ctx.inputSections.push_back(bss); - Defined(s->file, StringRef(), s->binding, s->stOther, s->type, + Defined(ctx, s->file, StringRef(), s->binding, s->stOther, s->type, /*value=*/0, s->size, bss) .overwrite(*s); } diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 3d02ef8b77abaa..0d3db373138874 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1156,14 +1156,14 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { fatal(toString(this) + ": common symbol '" + sym->getName() + "' has invalid alignment: " + Twine(value)); hasCommonSyms = true; - sym->resolve(ctx, CommonSymbol{this, StringRef(), binding, stOther, type, - value, size}); + sym->resolve(ctx, CommonSymbol{ctx, this, StringRef(), binding, stOther, + type, value, size}); continue; } // Handle global defined symbols. Defined::section will be set in postParse. - sym->resolve(ctx, Defined{this, StringRef(), binding, stOther, type, value, - size, nullptr}); + sym->resolve(ctx, Defined{ctx, this, StringRef(), binding, stOther, type, + value, size, nullptr}); } // Undefined symbols (excluding those defined relative to non-prevailing @@ -1219,7 +1219,7 @@ void ObjFile::initSectionsAndLocalSyms(bool ignoreComdats) { new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type, /*discardedSecIdx=*/secIdx); else - new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, + new (symbols[i]) Defined(ctx, this, name, STB_LOCAL, eSym.st_other, type, eSym.st_value, eSym.st_size, sec); symbols[i]->partition = 1; symbols[i]->isUsedInRegularObj = true; @@ -1765,11 +1765,12 @@ static void createBitcodeSymbol(Ctx &ctx, Symbol *&sym, } if (objSym.isCommon()) { - sym->resolve(ctx, CommonSymbol{&f, StringRef(), binding, visibility, + sym->resolve(ctx, CommonSymbol{ctx, &f, StringRef(), binding, visibility, STT_OBJECT, objSym.getCommonAlignment(), objSym.getCommonSize()}); } else { - Defined newSym(&f, StringRef(), binding, visibility, type, 0, 0, nullptr); + Defined newSym(ctx, &f, StringRef(), binding, visibility, type, 0, 0, + nullptr); if (objSym.canBeOmittedFromSymbolTable()) newSym.exportDynamic = false; sym->resolve(ctx, newSym); @@ -1849,14 +1850,14 @@ void BinaryFile::parse() { llvm::StringSaver &saver = lld::saver(); - ctx.symtab->addAndCheckDuplicate(ctx, Defined{this, saver.save(s + "_start"), - STB_GLOBAL, STV_DEFAULT, - STT_OBJECT, 0, 0, section}); ctx.symtab->addAndCheckDuplicate( - ctx, Defined{this, saver.save(s + "_end"), STB_GLOBAL, STV_DEFAULT, + ctx, Defined{ctx, this, saver.save(s + "_start"), STB_GLOBAL, STV_DEFAULT, + STT_OBJECT, 0, 0, section}); + ctx.symtab->addAndCheckDuplicate( + ctx, Defined{ctx, this, saver.save(s + "_end"), STB_GLOBAL, STV_DEFAULT, STT_OBJECT, data.size(), 0, section}); ctx.symtab->addAndCheckDuplicate( - ctx, Defined{this, saver.save(s + "_size"), STB_GLOBAL, STV_DEFAULT, + ctx, Defined{ctx, this, saver.save(s + "_size"), STB_GLOBAL, STV_DEFAULT, STT_OBJECT, data.size(), 0, nullptr}); } diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 2e9e8a7007bbf8..3b48fbe07bb082 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -70,8 +70,10 @@ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags, // If SHF_COMPRESSED is set, parse the header. The legacy .zdebug format is no // longer supported. - if (flags & SHF_COMPRESSED) + if (flags & SHF_COMPRESSED) { + Ctx &ctx = file->ctx; invokeELFT(parseCompressedHeader,); + } } // SHF_INFO_LINK and SHF_GROUP are normally resolved and not copied to the @@ -508,7 +510,8 @@ void InputSection::copyRelocations(Ctx &ctx, uint8_t *buf, } if (RelTy::HasAddend) - p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr; + p->r_addend = + sym.getVA(ctx, addend) - section->getOutputSection()->addr; // For SHF_ALLOC sections relocated by REL, append a relocation to // sec->relocations so that relocateAlloc transitively called by // writeSections will update the implicit addend. Non-SHF_ALLOC sections @@ -701,7 +704,7 @@ static int64_t getTlsTpOffset(Ctx &ctx, const Symbol &s) { // Variant 1. case EM_ARM: case EM_AARCH64: - return s.getVA(0) + ctx.arg.wordsize * 2 + + return s.getVA(ctx, 0) + ctx.arg.wordsize * 2 + ((tls->p_vaddr - ctx.arg.wordsize * 2) & (tls->p_align - 1)); case EM_MIPS: case EM_PPC: @@ -709,7 +712,7 @@ static int64_t getTlsTpOffset(Ctx &ctx, const Symbol &s) { // Adjusted Variant 1. TP is placed with a displacement of 0x7000, which is // to allow a signed 16-bit offset to reach 0x1000 of TCB/thread-library // data and 0xf000 of the program's TLS segment. - return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1)) - 0x7000; + return s.getVA(ctx, 0) + (tls->p_vaddr & (tls->p_align - 1)) - 0x7000; case EM_LOONGARCH: case EM_RISCV: // See the comment in handleTlsRelocation. For TLSDESC=>IE, @@ -717,7 +720,7 @@ static int64_t getTlsTpOffset(Ctx &ctx, const Symbol &s) { // `tls` may be null, the return value is ignored. if (s.type != STT_TLS) return 0; - return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1)); + return s.getVA(ctx, 0) + (tls->p_vaddr & (tls->p_align - 1)); // Variant 2. case EM_HEXAGON: @@ -725,7 +728,7 @@ static int64_t getTlsTpOffset(Ctx &ctx, const Symbol &s) { case EM_SPARCV9: case EM_386: case EM_X86_64: - return s.getVA(0) - tls->p_memsz - + return s.getVA(ctx, 0) - tls->p_memsz - ((-tls->p_vaddr - tls->p_memsz) & (tls->p_align - 1)); default: llvm_unreachable("unhandled ctx.arg.emachine"); @@ -743,13 +746,13 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, case R_AARCH64_AUTH: case R_RISCV_ADD: case R_RISCV_LEB128: - return r.sym->getVA(a); + return r.sym->getVA(ctx, a); case R_ADDEND: return a; case R_RELAX_HINT: return 0; case R_ARM_SBREL: - return r.sym->getVA(a) - getARMStaticBase(*r.sym); + return r.sym->getVA(ctx, a) - getARMStaticBase(*r.sym); case R_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: return r.sym->getGotVA(ctx) + a; @@ -767,9 +770,9 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, return ctx.in.gotPlt->getVA() + a - p; case R_GOTREL: case R_PPC64_RELAX_TOC: - return r.sym->getVA(a) - ctx.in.got->getVA(); + return r.sym->getVA(ctx, a) - ctx.in.got->getVA(); case R_GOTPLTREL: - return r.sym->getVA(a) - ctx.in.gotPlt->getVA(); + return r.sym->getVA(ctx, a) - ctx.in.gotPlt->getVA(); case R_GOTPLT: case R_RELAX_TLS_GD_TO_IE_GOTPLT: return r.sym->getGotVA(ctx) + a - ctx.in.gotPlt->getVA(); @@ -795,7 +798,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, r.type); return getLoongArchPageDelta(r.sym->getGotVA(ctx) + a, p, r.type); case R_MIPS_GOTREL: - return r.sym->getVA(a) - ctx.in.mipsGot->getGp(file); + return r.sym->getVA(ctx, a) - ctx.in.mipsGot->getGp(file); case R_MIPS_GOT_GP: return ctx.in.mipsGot->getGp(file) + a; case R_MIPS_GOT_GP_PC: { @@ -836,16 +839,16 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, return ctx.in.mipsGot->getVA() + ctx.in.mipsGot->getTlsIndexOffset(file) - ctx.in.mipsGot->getGp(file); case R_AARCH64_PAGE_PC: { - uint64_t val = r.sym->isUndefWeak() ? p + a : r.sym->getVA(a); + uint64_t val = r.sym->isUndefWeak() ? p + a : r.sym->getVA(ctx, a); return getAArch64Page(val) - getAArch64Page(p); } case R_RISCV_PC_INDIRECT: { if (const Relocation *hiRel = getRISCVPCRelHi20(this, r)) - return getRelocTargetVA(ctx, *hiRel, r.sym->getVA()); + return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx)); return 0; } case R_LOONGARCH_PAGE_PC: - return getLoongArchPageDelta(r.sym->getVA(a), p, r.type); + return getLoongArchPageDelta(r.sym->getVA(ctx, a), p, r.type); case R_PC: case R_ARM_PCA: { uint64_t dest; @@ -868,9 +871,9 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, else if (ctx.arg.emachine == EM_RISCV) dest = getRISCVUndefinedRelativeWeakVA(r.type, p) + a; else - dest = r.sym->getVA(a); + dest = r.sym->getVA(ctx, a); } else { - dest = r.sym->getVA(a); + dest = r.sym->getVA(ctx, a); } return dest - p; } @@ -891,7 +894,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, // target VA computation. return r.sym->getPltVA(ctx) - p; case R_PPC64_CALL: { - uint64_t symVA = r.sym->getVA(a); + uint64_t symVA = r.sym->getVA(ctx, a); // If we have an undefined weak symbol, we might get here with a symbol // address of zero. That could overflow, but the code must be unreachable, // so don't bother doing anything at all. @@ -910,7 +913,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, return getPPC64TocBase(ctx) + a; case R_RELAX_GOT_PC: case R_PPC64_RELAX_GOT_PC: - return r.sym->getVA(a) - p; + return r.sym->getVA(ctx, a) - p; case R_RELAX_TLS_GD_TO_LE: case R_RELAX_TLS_IE_TO_LE: case R_RELAX_TLS_LD_TO_LE: @@ -1016,8 +1019,8 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf, if (!ds && tombstone) { val = *tombstone; } else { - val = sym.getVA(addend) - - (f->getRelocTargetSym(*it).getVA(0) + getAddend(*it)); + val = sym.getVA(ctx, addend) - + (f->getRelocTargetSym(*it).getVA(ctx) + getAddend(*it)); } if (overwriteULEB128(bufLoc, val) >= 0x80) errorOrWarn(getLocation(offset) + ": ULEB128 value " + Twine(val) + @@ -1083,7 +1086,8 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf, // sections. if (LLVM_LIKELY(expr == R_ABS) || expr == R_DTPREL || expr == R_GOTPLTREL || expr == R_RISCV_ADD) { - target.relocateNoSym(bufLoc, type, SignExtend64(sym.getVA(addend))); + target.relocateNoSym(bufLoc, type, + SignExtend64(sym.getVA(ctx, addend))); continue; } @@ -1116,7 +1120,7 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf, warn(msg); target.relocateNoSym( bufLoc, type, - SignExtend64(sym.getVA(addend - offset - outSecOff))); + SignExtend64(sym.getVA(ctx, addend - offset - outSecOff))); } } diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 0560065ffa4780..d2088b4c648180 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -227,8 +227,8 @@ void LinkerScript::addSymbol(SymbolAssignment *cmd) { // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`. uint64_t symValue = value.sec ? 0 : value.getValue(); - Defined newSym(createInternalFile(ctx, cmd->location), cmd->name, STB_GLOBAL, - visibility, value.type, symValue, 0, sec); + Defined newSym(ctx, createInternalFile(ctx, cmd->location), cmd->name, + STB_GLOBAL, visibility, value.type, symValue, 0, sec); Symbol *sym = ctx.symtab->insert(cmd->name); sym->mergeProperties(newSym); @@ -244,7 +244,7 @@ void LinkerScript::declareSymbol(SymbolAssignment *cmd) { return; uint8_t visibility = cmd->hidden ? STV_HIDDEN : STV_DEFAULT; - Defined newSym(ctx.internalFile, cmd->name, STB_GLOBAL, visibility, + Defined newSym(ctx, ctx.internalFile, cmd->name, STB_GLOBAL, visibility, STT_NOTYPE, 0, 0, nullptr); // If the symbol is already defined, its order is 0 (with absence indicating diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index 6bbc1ecc646fdd..afaf04dc72fe6c 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -65,10 +65,10 @@ static std::vector getSymbols(Ctx &ctx) { } // Returns a map from sections to their symbols. -static SymbolMapTy getSectionSyms(ArrayRef syms) { +static SymbolMapTy getSectionSyms(Ctx &ctx, ArrayRef syms) { SymbolMapTy ret; for (Defined *dr : syms) - ret[dr->section].emplace_back(dr, dr->getVA()); + ret[dr->section].emplace_back(dr, dr->getVA(ctx)); // Sort symbols by address. We want to print out symbols in the // order in the output file rather than the order they appeared @@ -95,7 +95,7 @@ getSymbolStrings(Ctx &ctx, ArrayRef syms) { parallelFor(0, syms.size(), [&](size_t i) { raw_string_ostream os(strs[i]); OutputSection *osec = syms[i]->getOutputSection(); - uint64_t vma = syms[i]->getVA(); + uint64_t vma = syms[i]->getVA(ctx); uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0; writeHeader(ctx, os, vma, lma, syms[i]->getSize(), 1); os << indent16 << toString(*syms[i]); @@ -149,7 +149,7 @@ static void printEhFrame(Ctx &ctx, raw_ostream &os, const EhFrameSection *sec) { static void writeMapFile(Ctx &ctx, raw_fd_ostream &os) { // Collect symbol info that we want to print out. std::vector syms = getSymbols(ctx); - SymbolMapTy sectionSyms = getSectionSyms(syms); + SymbolMapTy sectionSyms = getSectionSyms(ctx, syms); DenseMap symStr = getSymbolStrings(ctx, syms); // Print out the header line. diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 309039fe7e204a..6cae7cf8f8599d 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -624,7 +624,7 @@ encodeOneCrel(Ctx &ctx, raw_svector_ostream &os, if (d) { SectionBase *section = d->section; assert(section->isLive()); - addend = sym.getVA(addend) - section->getOutputSection()->addr; + addend = sym.getVA(ctx, addend) - section->getOutputSection()->addr; } else { // Encode R_*_NONE(symidx=0). symidx = type = addend = 0; @@ -882,7 +882,11 @@ void OutputSection::checkDynRelAddends(Ctx &ctx) { // for input .rel[a]. sections which we simply pass through to the // output. We skip over those and only look at the synthetic relocation // sections created during linking. - const auto *sec = dyn_cast(sections[i]); + if (!SyntheticSection::classof(sections[i]) || + !is_contained({ELF::SHT_REL, ELF::SHT_RELA, ELF::SHT_RELR}, + sections[i]->type)) + return; + const auto *sec = cast(sections[i]); if (!sec) return; for (const DynamicReloc &rel : sec->relocs) { diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 0188d658f9210e..d40348a7b30d8f 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -315,10 +315,10 @@ static SmallSet getSymbolsAt(Ctx &ctx, SharedSymbol &ss) { // in .bss and in the case of a canonical plt entry it is in .plt. This function // replaces the existing symbol with a Defined pointing to the appropriate // location. -static void replaceWithDefined(Symbol &sym, SectionBase &sec, uint64_t value, - uint64_t size) { +static void replaceWithDefined(Ctx &ctx, Symbol &sym, SectionBase &sec, + uint64_t value, uint64_t size) { Symbol old = sym; - Defined(sym.file, StringRef(), sym.binding, sym.stOther, sym.type, value, + Defined(ctx, sym.file, StringRef(), sym.binding, sym.stOther, sym.type, value, size, &sec) .overwrite(sym); @@ -398,7 +398,7 @@ template static void addCopyRelSymbol(Ctx &ctx, SharedSymbol &ss) { // dynamic symbol for each one. This causes the copy relocation to correctly // interpose any aliases. for (SharedSymbol *sym : getSymbolsAt(ctx, ss)) - replaceWithDefined(*sym, *sec, 0, sym->size); + replaceWithDefined(ctx, *sym, *sec, 0, sym->size); ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->copyRel, *sec, 0, ss); } @@ -1807,7 +1807,7 @@ void elf::postScanRelocations(Ctx &ctx) { } else { assert(sym.isFunc() && sym.hasFlag(NEEDS_PLT)); if (!sym.isDefined()) { - replaceWithDefined(sym, *ctx.in.plt, + replaceWithDefined(ctx, sym, *ctx.in.plt, ctx.target->pltHeaderSize + ctx.target->pltEntrySize * sym.getPltIdx(ctx), 0); @@ -2257,7 +2257,7 @@ std::pair ThunkCreator::getThunk(InputSection *isec, if (isThunkSectionCompatible(isec, t->getThunkTargetSym()->section) && t->isCompatibleWith(*isec, rel) && ctx.target->inBranchRange(rel.type, src, - t->getThunkTargetSym()->getVA(-pcBias))) + t->getThunkTargetSym()->getVA(ctx, -pcBias))) return std::make_pair(t, false); // No existing compatible Thunk in range, create a new one @@ -2281,7 +2281,8 @@ std::pair ThunkCreator::getSyntheticLandingPad(Defined &d, // relocation back to its original non-Thunk target. bool ThunkCreator::normalizeExistingThunk(Relocation &rel, uint64_t src) { if (Thunk *t = thunks.lookup(rel.sym)) { - if (ctx.target->inBranchRange(rel.type, src, rel.sym->getVA(rel.addend))) + if (ctx.target->inBranchRange(rel.type, src, + rel.sym->getVA(ctx, rel.addend))) return true; rel.sym = &t->destination; rel.addend = t->addend; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 3caa609338e068..da35bf858cb371 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -44,13 +44,13 @@ LLVM_ATTRIBUTE_UNUSED static inline void assertSymbols() { } // Returns a symbol for an error message. -static std::string maybeDemangleSymbol(StringRef symName) { - return elf::ctx.arg.demangle ? demangle(symName.str()) : symName.str(); +static std::string maybeDemangleSymbol(Ctx &ctx, StringRef symName) { + return ctx.arg.demangle ? demangle(symName.str()) : symName.str(); } std::string lld::toString(const elf::Symbol &sym) { StringRef name = sym.getName(); - std::string ret = maybeDemangleSymbol(name); + std::string ret = maybeDemangleSymbol(ctx, name); const char *suffix = sym.getVersionSuffix(); if (*suffix == '@') @@ -58,7 +58,7 @@ std::string lld::toString(const elf::Symbol &sym) { return ret; } -static uint64_t getSymVA(const Symbol &sym, int64_t addend) { +static uint64_t getSymVA(Ctx &ctx, const Symbol &sym, int64_t addend) { switch (sym.kind()) { case Symbol::DefinedKind: { auto &d = cast(sym); @@ -141,8 +141,8 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) { llvm_unreachable("invalid symbol kind"); } -uint64_t Symbol::getVA(int64_t addend) const { - return getSymVA(*this, addend) + addend; +uint64_t Symbol::getVA(Ctx &ctx, int64_t addend) const { + return getSymVA(ctx, *this, addend) + addend; } uint64_t Symbol::getGotVA(Ctx &ctx) const { @@ -617,7 +617,7 @@ void Symbol::resolve(Ctx &ctx, const LazySymbol &other) { // For common objects, we want to look for global or weak definitions that // should be extracted as the canonical definition instead. - if (LLVM_UNLIKELY(isCommon()) && elf::ctx.arg.fortranCommon && + if (LLVM_UNLIKELY(isCommon()) && ctx.arg.fortranCommon && other.file->shouldExtractForCommon(getName())) { ctx.backwardReferences.erase(this); other.overwrite(*this); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 010ae9742378b9..339f32e05f1625 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -210,7 +210,7 @@ class Symbol { bool isInGot(Ctx &ctx) const { return getGotIdx(ctx) != uint32_t(-1); } bool isInPlt(Ctx &ctx) const { return getPltIdx(ctx) != uint32_t(-1); } - uint64_t getVA(int64_t addend = 0) const; + uint64_t getVA(Ctx &, int64_t addend = 0) const; uint64_t getGotOffset(Ctx &) const; uint64_t getGotVA(Ctx &) const; @@ -363,8 +363,9 @@ class Symbol { // Represents a symbol that is defined in the current output file. class Defined : public Symbol { public: - Defined(InputFile *file, StringRef name, uint8_t binding, uint8_t stOther, - uint8_t type, uint64_t value, uint64_t size, SectionBase *section) + Defined(Ctx &ctx, InputFile *file, StringRef name, uint8_t binding, + uint8_t stOther, uint8_t type, uint64_t value, uint64_t size, + SectionBase *section) : Symbol(DefinedKind, file, name, binding, stOther, type), value(value), size(size), section(section) { exportDynamic = ctx.arg.exportDynamic; @@ -401,7 +402,7 @@ class Defined : public Symbol { // section. (Therefore, the later passes don't see any CommonSymbols.) class CommonSymbol : public Symbol { public: - CommonSymbol(InputFile *file, StringRef name, uint8_t binding, + CommonSymbol(Ctx &ctx, InputFile *file, StringRef name, uint8_t binding, uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size) : Symbol(CommonKind, file, name, binding, stOther, type), alignment(alignment), size(size) { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index e18e7a32df86c7..7a344635a1cb53 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -276,8 +276,8 @@ InputSection *elf::createInterpSection(Ctx &ctx) { Defined *elf::addSyntheticLocal(Ctx &ctx, StringRef name, uint8_t type, uint64_t value, uint64_t size, InputSectionBase §ion) { - Defined *s = makeDefined(section.file, name, STB_LOCAL, STV_DEFAULT, type, - value, size, §ion); + Defined *s = makeDefined(ctx, section.file, name, STB_LOCAL, STV_DEFAULT, + type, value, size, §ion); if (ctx.in.symTab) ctx.in.symTab->addSymbol(s); @@ -749,7 +749,7 @@ void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend, if (const OutputSection *os = sym.getOutputSection()) g.pagesMap.insert({os, {}}); else - g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(addend))}, 0}); + g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(ctx, addend))}, 0}); } else if (sym.isTls()) g.tls.insert({&sym, 0}); else if (sym.isPreemptible && expr == R_ABS) @@ -808,10 +808,11 @@ uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f, uint64_t index = 0; if (const OutputSection *outSec = sym.getOutputSection()) { uint64_t secAddr = getMipsPageAddr(outSec->addr); - uint64_t symAddr = getMipsPageAddr(sym.getVA(addend)); + uint64_t symAddr = getMipsPageAddr(sym.getVA(ctx, addend)); index = g.pagesMap.lookup(outSec).firstIndex + (symAddr - secAddr) / 0xffff; } else { - index = g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(addend))}); + index = + g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(ctx, addend))}); } return index * ctx.arg.wordsize; } @@ -1099,7 +1100,7 @@ uint64_t MipsGotSection::getGp(const InputFile *f) const { // returns "common" _gp value. For secondary GOTs calculate // individual _gp values. if (!f || f->mipsGotIndex == uint32_t(-1) || f->mipsGotIndex == 0) - return ctx.sym.mipsGp->getVA(0); + return ctx.sym.mipsGp->getVA(ctx, 0); return getVA() + gots[f->mipsGotIndex].startIndex * ctx.arg.wordsize + 0x7ff0; } @@ -1124,7 +1125,7 @@ void MipsGotSection::writeTo(uint8_t *buf) { auto write = [&](size_t i, const Symbol *s, int64_t a) { uint64_t va = a; if (s) - va = s->getVA(a); + va = s->getVA(ctx, a); writeUint(ctx, buf + i * ctx.arg.wordsize, va); }; // Write 'page address' entries to the local part of the GOT. @@ -1522,10 +1523,10 @@ DynamicSection::computeContents() { if (Symbol *b = ctx.symtab->find(ctx.arg.init)) if (b->isDefined()) - addInt(DT_INIT, b->getVA()); + addInt(DT_INIT, b->getVA(ctx)); if (Symbol *b = ctx.symtab->find(ctx.arg.fini)) if (b->isDefined()) - addInt(DT_FINI, b->getVA()); + addInt(DT_FINI, b->getVA(ctx)); } if (part.verSym && part.verSym->isNeeded()) @@ -2288,7 +2289,7 @@ template void SymbolTableSection::writeTo(uint8_t *buf) { const uint32_t shndx = getSymSectionIndex(sym); if (isDefinedHere) { eSym->st_shndx = shndx; - eSym->st_value = sym->getVA(); + eSym->st_value = sym->getVA(ctx); // Copy symbol size if it is a defined symbol. st_size is not // significant for undefined symbols, so whether copying it or not is up // to us if that's the case. We'll leave it as zero because by not @@ -3241,7 +3242,7 @@ void DebugNamesSection::getNameRelocs( Relocs rels) { for (const RelTy &rel : rels) { Symbol &sym = file.getRelocTargetSym(rel); - relocs[rel.r_offset] = sym.getVA(getAddend(rel)); + relocs[rel.r_offset] = sym.getVA(ctx, getAddend(rel)); } } @@ -4356,11 +4357,11 @@ void PPC64LongBranchTargetSection::writeTo(uint8_t *buf) { for (auto entry : entries) { const Symbol *sym = entry.first; int64_t addend = entry.second; - assert(sym->getVA()); + assert(sym->getVA(ctx)); // Need calls to branch to the local entry-point since a long-branch // must be a local-call. write64(ctx, buf, - sym->getVA(addend) + + sym->getVA(ctx, addend) + getPPC64GlobalEntryToLocalEntryOffset(sym->stOther)); buf += 8; } @@ -4616,7 +4617,7 @@ createMemtagGlobalDescriptors(Ctx &ctx, for (const Symbol *sym : symbols) { if (!includeInSymtab(ctx, *sym)) continue; - const uint64_t addr = sym->getVA(); + const uint64_t addr = sym->getVA(ctx); const uint64_t size = sym->getSize(); if (addr <= kMemtagGranuleSize && buf != nullptr) @@ -4653,8 +4654,8 @@ createMemtagGlobalDescriptors(Ctx &ctx, bool MemtagGlobalDescriptors::updateAllocSize(Ctx &ctx) { size_t oldSize = getSize(); std::stable_sort(symbols.begin(), symbols.end(), - [](const Symbol *s1, const Symbol *s2) { - return s1->getVA() < s2->getVA(); + [&ctx = ctx](const Symbol *s1, const Symbol *s2) { + return s1->getVA(ctx) < s2->getVA(ctx); }); return oldSize != getSize(); } @@ -4681,8 +4682,8 @@ static Defined *addOptionalRegular(Ctx &ctx, StringRef name, SectionBase *sec, if (!s || s->isDefined() || s->isCommon()) return nullptr; - s->resolve(ctx, Defined{ctx.internalFile, StringRef(), STB_GLOBAL, stOther, - STT_NOTYPE, val, + s->resolve(ctx, Defined{ctx, ctx.internalFile, StringRef(), STB_GLOBAL, + stOther, STT_NOTYPE, val, /*size=*/0, sec}); s->isUsedInRegularObj = true; return cast(s); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index d64c4aad8c552b..3573767671feb1 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -547,13 +547,7 @@ class RelocationBaseSection : public SyntheticSection { void mergeRels(); void partitionRels(); void finalizeContents() override; - static bool classof(const SectionBase *d) { - return SyntheticSection::classof(d) && - (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL || - d->type == llvm::ELF::SHT_RELR || - (d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR && - elf::ctx.arg.emachine == llvm::ELF::EM_AARCH64)); - } + int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index 971b2724b3e26f..94c0b2409c6c7c 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -464,7 +464,7 @@ class PPC64R2SaveStub final : public Thunk { // This is similar to the handling for ARMThunk. bool mayUseShortThunk = true; int64_t computeOffset() const { - return destination.getVA() - (getThunkTargetSym()->getVA() + 4); + return destination.getVA(ctx) - (getThunkTargetSym()->getVA(ctx) + 4); } }; @@ -550,7 +550,7 @@ void Thunk::setOffset(uint64_t newOffset) { // AArch64 Thunk base class. static uint64_t getAArch64ThunkDestVA(Ctx &ctx, const Symbol &s, int64_t a) { - uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(a); + uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx, a); return v; } @@ -558,7 +558,7 @@ bool AArch64Thunk::getMayUseShortThunk() { if (!mayUseShortThunk) return false; uint64_t s = getAArch64ThunkDestVA(ctx, destination, addend); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); mayUseShortThunk = llvm::isInt<28>(s - p); return mayUseShortThunk; } @@ -569,7 +569,7 @@ void AArch64Thunk::writeTo(uint8_t *buf) { return; } uint64_t s = getAArch64ThunkDestVA(ctx, destination, addend); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); write32(ctx, buf, 0x14000000); // b S ctx.target->relocateNoSym(buf, R_AARCH64_CALL26, s - p); } @@ -592,7 +592,7 @@ void AArch64ABSLongThunk::writeLong(uint8_t *buf) { // AArch64BTILandingPadThunk that defines landingPad. assert(!mayNeedLandingPad || landingPad != nullptr); uint64_t s = mayNeedLandingPad - ? landingPad->getVA(0) + ? landingPad->getVA(ctx, 0) : getAArch64ThunkDestVA(ctx, destination, addend); memcpy(buf, data, sizeof(data)); ctx.target->relocateNoSym(buf + 8, R_AARCH64_ABS64, s); @@ -621,9 +621,9 @@ void AArch64ADRPThunk::writeLong(uint8_t *buf) { // AArch64BTILandingPadThunk that defines landingPad. assert(!mayNeedLandingPad || landingPad != nullptr); uint64_t s = mayNeedLandingPad - ? landingPad->getVA(0) + ? landingPad->getVA(ctx, 0) : getAArch64ThunkDestVA(ctx, destination, addend); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); memcpy(buf, data, sizeof(data)); ctx.target->relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21, getAArch64Page(s) - getAArch64Page(p)); @@ -656,8 +656,8 @@ bool AArch64BTILandingPadThunk::getMayUseShortThunk() { return false; // If the target is the following instruction then we can fall // through without the indirect branch. - uint64_t s = destination.getVA(addend); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t s = destination.getVA(ctx, addend); + uint64_t p = getThunkTargetSym()->getVA(ctx); // This function is called before addresses are stable. We need to // work out the range from the thunk to the next section but the // address of the start of the next section depends on the size of @@ -670,8 +670,8 @@ bool AArch64BTILandingPadThunk::getMayUseShortThunk() { } void AArch64BTILandingPadThunk::writeLong(uint8_t *buf) { - uint64_t s = destination.getVA(addend); - uint64_t p = getThunkTargetSym()->getVA() + 4; + uint64_t s = destination.getVA(ctx, addend); + uint64_t p = getThunkTargetSym()->getVA(ctx) + 4; write32(ctx, buf, 0xd503245f); // BTI c write32(ctx, buf + 4, 0x14000000); // B S ctx.target->relocateNoSym(buf + 4, R_AARCH64_CALL26, s - p); @@ -679,7 +679,7 @@ void AArch64BTILandingPadThunk::writeLong(uint8_t *buf) { // ARM Target Thunks static uint64_t getARMThunkDestVA(Ctx &ctx, const Symbol &s) { - uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(); + uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx); return SignExtend64<32>(v); } @@ -693,7 +693,7 @@ bool ARMThunk::getMayUseShortThunk() { mayUseShortThunk = false; return false; } - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); int64_t offset = s - p - 8; mayUseShortThunk = llvm::isInt<26>(offset); return mayUseShortThunk; @@ -706,7 +706,7 @@ void ARMThunk::writeTo(uint8_t *buf) { } uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); int64_t offset = s - p - 8; write32(ctx, buf, 0xea000000); // b S ctx.target->relocateNoSym(buf, R_ARM_JUMP24, offset); @@ -736,7 +736,7 @@ bool ThumbThunk::getMayUseShortThunk() { mayUseShortThunk = false; return false; } - uint64_t p = getThunkTargetSym()->getVA() & ~1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~1; int64_t offset = s - p - 4; mayUseShortThunk = llvm::isInt<25>(offset); return mayUseShortThunk; @@ -749,7 +749,7 @@ void ThumbThunk::writeTo(uint8_t *buf) { } uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); int64_t offset = s - p - 4; write16(ctx, buf + 0, 0xf000); // b.w S write16(ctx, buf + 2, 0xb000); @@ -806,7 +806,7 @@ void ARMV7PILongThunk::writeLong(uint8_t *buf) { write32(ctx, buf + 8, 0xe08cc00f); // L1: add ip, ip, pc write32(ctx, buf + 12, 0xe12fff1c); // bx ip uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t p = getThunkTargetSym()->getVA(ctx); int64_t offset = s - p - 16; ctx.target->relocateNoSym(buf, R_ARM_MOVW_PREL_NC, offset); ctx.target->relocateNoSym(buf + 4, R_ARM_MOVT_PREL, offset); @@ -826,7 +826,7 @@ void ThumbV7PILongThunk::writeLong(uint8_t *buf) { write16(ctx, buf + 8, 0x44fc); // L1: add ip, pc write16(ctx, buf + 10, 0x4760); // bx ip uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1; int64_t offset = s - p - 12; ctx.target->relocateNoSym(buf, R_ARM_THM_MOVW_PREL_NC, offset); ctx.target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_PREL, offset); @@ -904,7 +904,7 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *buf) { 0x46c0); // nop ; pad to 4-byte boundary write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4) uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1; ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12); } @@ -992,7 +992,7 @@ void ARMV4PILongBXThunk::writeLong(uint8_t *buf) { write32(ctx, buf + 8, 0xe12fff1c); // bx ip write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1; ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12); } @@ -1009,7 +1009,7 @@ void ARMV4PILongThunk::writeLong(uint8_t *buf) { write32(ctx, buf + 4, 0xe08ff00c); // L1: add pc, pc, r12 write32(ctx, buf + 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1; ctx.target->relocateNoSym(buf + 8, R_ARM_REL32, s - p - 12); } @@ -1029,7 +1029,7 @@ void ThumbV4PILongBXThunk::writeLong(uint8_t *buf) { write32(ctx, buf + 8, 0xe08cf00f); // L1: add pc, r12, pc write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1; ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 16); } @@ -1051,7 +1051,7 @@ void ThumbV4PILongThunk::writeLong(uint8_t *buf) { write32(ctx, buf + 12, 0xe12fff1c); // bx ip write32(ctx, buf + 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) uint64_t s = getARMThunkDestVA(ctx, destination); - uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1; ctx.target->relocateNoSym(buf + 16, R_ARM_REL32, s - p - 16); } @@ -1067,7 +1067,7 @@ void ThumbV4PILongThunk::addSymbols(ThunkSection &isec) { // Use the long jump which covers a range up to 8MiB. void AVRThunk::writeTo(uint8_t *buf) { write32(ctx, buf, 0x940c); // jmp func - ctx.target->relocateNoSym(buf, R_AVR_CALL, destination.getVA()); + ctx.target->relocateNoSym(buf, R_AVR_CALL, destination.getVA(ctx)); } void AVRThunk::addSymbols(ThunkSection &isec) { @@ -1077,7 +1077,7 @@ void AVRThunk::addSymbols(ThunkSection &isec) { // Write MIPS LA25 thunk code to call PIC function from the non-PIC one. void MipsThunk::writeTo(uint8_t *buf) { - uint64_t s = destination.getVA(); + uint64_t s = destination.getVA(ctx); write32(ctx, buf, 0x3c190000); // lui $25, %hi(func) write32(ctx, buf + 4, 0x08000000 | (s >> 2)); // j func write32(ctx, buf + 8, 0x27390000); // addiu $25, $25, %lo(func) @@ -1099,7 +1099,7 @@ InputSection *MipsThunk::getTargetInputSection() const { // Write microMIPS R2-R5 LA25 thunk code // to call PIC function from the non-PIC one. void MicroMipsThunk::writeTo(uint8_t *buf) { - uint64_t s = destination.getVA(); + uint64_t s = destination.getVA(ctx); write16(ctx, buf, 0x41b9); // lui $25, %hi(func) write16(ctx, buf + 4, 0xd400); // j func write16(ctx, buf + 8, 0x3339); // addiu $25, $25, %lo(func) @@ -1124,8 +1124,8 @@ InputSection *MicroMipsThunk::getTargetInputSection() const { // Write microMIPS R6 LA25 thunk code // to call PIC function from the non-PIC one. void MicroMipsR6Thunk::writeTo(uint8_t *buf) { - uint64_t s = destination.getVA(); - uint64_t p = getThunkTargetSym()->getVA(); + uint64_t s = destination.getVA(ctx); + uint64_t p = getThunkTargetSym()->getVA(ctx); write16(ctx, buf, 0x1320); // lui $25, %hi(func) write16(ctx, buf + 4, 0x3339); // addiu $25, $25, %lo(func) write16(ctx, buf + 8, 0x9400); // bc func @@ -1213,9 +1213,9 @@ void PPC32LongThunk::addSymbols(ThunkSection &isec) { void PPC32LongThunk::writeTo(uint8_t *buf) { auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; }; auto lo = [](uint32_t v) -> uint16_t { return v; }; - uint32_t d = destination.getVA(addend); + uint32_t d = destination.getVA(ctx, addend); if (ctx.arg.isPic) { - uint32_t off = d - (getThunkTargetSym()->getVA() + 8); + uint32_t off = d - (getThunkTargetSym()->getVA(ctx) + 8); write32(ctx, buf + 0, 0x7c0802a6); // mflr r12,0 write32(ctx, buf + 4, 0x429f0005); // bcl r20,r31,.+4 write32(ctx, buf + 8, 0x7d8802a6); // mtctr r12 @@ -1269,7 +1269,7 @@ void PPC64R2SaveStub::writeTo(uint8_t *buf) { write32(ctx, buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b } else if (isInt<34>(offset)) { int nextInstOffset; - uint64_t tocOffset = destination.getVA() - getPPC64TocBase(ctx); + uint64_t tocOffset = destination.getVA(ctx) - getPPC64TocBase(ctx); if (tocOffset >> 16 > 0) { const uint64_t addi = ADDI_R12_TO_R12_NO_DISP | (tocOffset & 0xffff); const uint64_t addis = @@ -1306,8 +1306,8 @@ bool PPC64R2SaveStub::isCompatibleWith(const InputSection &isec, void PPC64R12SetupStub::writeTo(uint8_t *buf) { int64_t offset = - (gotPlt ? destination.getGotPltVA(ctx) : destination.getVA()) - - getThunkTargetSym()->getVA(); + (gotPlt ? destination.getGotPltVA(ctx) : destination.getVA(ctx)) - + getThunkTargetSym()->getVA(ctx); if (!isInt<34>(offset)) reportRangeError(ctx, buf, offset, 34, destination, "R12 setup stub offset"); @@ -1393,7 +1393,7 @@ static Thunk *addThunkAArch64(Ctx &ctx, RelType type, Symbol &s, int64_t a) { // TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for // Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state). static Thunk *addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s, int64_t a) { - bool thumb_target = s.getVA(a) & 1; + bool thumb_target = s.getVA(ctx, a) & 1; switch (reloc) { case R_ARM_PC24: diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 2cd4478d00cf5d..ecd4f5e470833c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -145,8 +145,8 @@ static Defined *addOptionalRegular(Ctx &ctx, StringRef name, SectionBase *sec, if (!s || s->isDefined() || s->isCommon()) return nullptr; - s->resolve(ctx, Defined{ctx.internalFile, StringRef(), STB_GLOBAL, stOther, - STT_NOTYPE, val, + s->resolve(ctx, Defined{ctx, ctx.internalFile, StringRef(), STB_GLOBAL, + stOther, STT_NOTYPE, val, /*size=*/0, sec}); s->isUsedInRegularObj = true; return cast(s); @@ -158,7 +158,7 @@ void elf::addReservedSymbols(Ctx &ctx) { if (ctx.arg.emachine == EM_MIPS) { auto addAbsolute = [&](StringRef name) { Symbol *sym = - ctx.symtab->addSymbol(Defined{ctx.internalFile, name, STB_GLOBAL, + ctx.symtab->addSymbol(Defined{ctx, ctx.internalFile, name, STB_GLOBAL, STV_HIDDEN, STT_NOTYPE, 0, 0, nullptr}); sym->isUsedInRegularObj = true; return cast(sym); @@ -211,9 +211,9 @@ void elf::addReservedSymbols(Ctx &ctx) { if (ctx.arg.emachine == EM_PPC64) gotOff = 0x8000; - s->resolve(ctx, - Defined{ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, - STT_NOTYPE, gotOff, /*size=*/0, ctx.out.elfHeader}); + s->resolve(ctx, Defined{ctx, ctx.internalFile, StringRef(), STB_GLOBAL, + STV_HIDDEN, STT_NOTYPE, gotOff, /*size=*/0, + ctx.out.elfHeader}); ctx.sym.globalOffsetTable = cast(s); } @@ -534,7 +534,7 @@ template void Writer::addSectionSymbols() { // Set the symbol to be relative to the output section so that its st_value // equals the output section address. Note, there may be a gap between the // start of the output section and isec. - ctx.in.symTab->addSymbol(makeDefined(isec->file, "", STB_LOCAL, + ctx.in.symTab->addSymbol(makeDefined(ctx, isec->file, "", STB_LOCAL, /*stOther=*/0, STT_SECTION, /*value=*/0, /*size=*/0, &osec)); } @@ -1504,9 +1504,9 @@ template void Writer::finalizeAddressDependentContent() { // .rela.dyn. See also AArch64::relocate. if (part.relrAuthDyn) { auto it = llvm::remove_if( - part.relrAuthDyn->relocs, [&part](const RelativeReloc &elem) { + part.relrAuthDyn->relocs, [this, &part](const RelativeReloc &elem) { const Relocation &reloc = elem.inputSec->relocs()[elem.relocIdx]; - if (isInt<32>(reloc.sym->getVA(reloc.addend))) + if (isInt<32>(reloc.sym->getVA(ctx, reloc.addend))) return false; part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, elem.inputSec, reloc.offset, @@ -1690,10 +1690,9 @@ static void removeUnusedSyntheticSections(Ctx &ctx) { // finalizeAddressDependentContent, making .rela.dyn no longer empty. // Conservatively keep .rela.dyn. .relr.auth.dyn can be made empty, but // we would fail to remove it here. - if (ctx.arg.emachine == EM_AARCH64 && ctx.arg.relrPackDynRelocs) - if (auto *relSec = dyn_cast(sec)) - if (relSec == ctx.mainPart->relaDyn.get()) - return false; + if (ctx.arg.emachine == EM_AARCH64 && ctx.arg.relrPackDynRelocs && + sec == ctx.mainPart->relaDyn.get()) + return false; unused.insert(sec); return true; }); @@ -1734,7 +1733,7 @@ template void Writer::finalizeSections() { // https://sourceware.org/ml/binutils/2002-03/msg00360.html if (ctx.mainPart->dynamic->parent) { Symbol *s = ctx.symtab->addSymbol(Defined{ - ctx.internalFile, "_DYNAMIC", STB_WEAK, STV_HIDDEN, STT_NOTYPE, + ctx, ctx.internalFile, "_DYNAMIC", STB_WEAK, STV_HIDDEN, STT_NOTYPE, /*value=*/0, /*size=*/0, ctx.mainPart->dynamic.get()}); s->isUsedInRegularObj = true; } @@ -1775,7 +1774,7 @@ template void Writer::finalizeSections() { // define _TLS_MODULE_BASE_ relative to the first TLS section. Symbol *s = ctx.symtab->find("_TLS_MODULE_BASE_"); if (s && s->isUndefined()) { - s->resolve(ctx, Defined{ctx.internalFile, StringRef(), STB_GLOBAL, + s->resolve(ctx, Defined{ctx, ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, STT_TLS, /*value=*/0, 0, /*section=*/nullptr}); ctx.sym.tlsModuleBase = cast(s); @@ -2713,7 +2712,7 @@ template void Writer::checkSections() { static uint64_t getEntryAddr(Ctx &ctx) { // Case 1, 2 or 3 if (Symbol *b = ctx.symtab->find(ctx.arg.entry)) - return b->getVA(); + return b->getVA(ctx); // Case 4 uint64_t addr; diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h index 41d8eeef469eab..c9cddee6baa2da 100644 --- a/lldb/include/lldb/Target/Language.h +++ b/lldb/include/lldb/Target/Language.h @@ -363,6 +363,15 @@ class Language : public PluginInterface { return false; } + /// Returns a boolean indicating whether two symbol contexts are equal for the + /// purposes of frame comparison. If the plugin has no opinion, it should + /// return nullopt. + virtual std::optional + AreEqualForFrameComparison(const SymbolContext &sc1, + const SymbolContext &sc2) const { + return {}; + } + /// Returns true if this Language supports exception breakpoints on throw via /// a corresponding LanguageRuntime plugin. virtual bool SupportsExceptionBreakpointsOnThrow() const { return false; } diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp index 934f23b3b21a28..ef5b4b5c434d16 100644 --- a/lldb/source/Target/ThreadPlanStepOverRange.cpp +++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp @@ -11,6 +11,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/LineTable.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" @@ -103,6 +104,10 @@ void ThreadPlanStepOverRange::SetupAvoidNoDebug( bool ThreadPlanStepOverRange::IsEquivalentContext( const SymbolContext &context) { + if (Language *language = Language::FindPlugin(context.GetLanguage())) + if (std::optional maybe_equivalent = + language->AreEqualForFrameComparison(context, m_addr_context)) + return *maybe_equivalent; // Match as much as is specified in the m_addr_context: This is a fairly // loose sanity check. Note, sometimes the target doesn't get filled in so I // left out the target check. And sometimes the module comes in as the .o diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index fa07b3a9e8b14f..e631e3899fd4de 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -358,20 +358,21 @@ struct CounterMappingRegion { struct CountedRegion : public CounterMappingRegion { uint64_t ExecutionCount; uint64_t FalseExecutionCount; - bool Folded; + bool TrueFolded; + bool FalseFolded; bool HasSingleByteCoverage; CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, bool HasSingleByteCoverage) : CounterMappingRegion(R), ExecutionCount(ExecutionCount), - FalseExecutionCount(0), Folded(false), + FalseExecutionCount(0), TrueFolded(false), FalseFolded(true), HasSingleByteCoverage(HasSingleByteCoverage) {} CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, uint64_t FalseExecutionCount, bool HasSingleByteCoverage) : CounterMappingRegion(R), ExecutionCount(ExecutionCount), - FalseExecutionCount(FalseExecutionCount), Folded(false), - HasSingleByteCoverage(HasSingleByteCoverage) {} + FalseExecutionCount(FalseExecutionCount), TrueFolded(false), + FalseFolded(false), HasSingleByteCoverage(HasSingleByteCoverage) {} }; /// MCDC Record grouping all information together. @@ -719,10 +720,10 @@ struct FunctionRecord { Region.Kind == CounterMappingRegion::MCDCBranchRegion) { CountedBranchRegions.emplace_back(Region, Count, FalseCount, HasSingleByteCoverage); - // If both counters are hard-coded to zero, then this region represents a + // If either counter is hard-coded to zero, then this region represents a // constant-folded branch. - if (Region.Count.isZero() && Region.FalseCount.isZero()) - CountedBranchRegions.back().Folded = true; + CountedBranchRegions.back().TrueFolded = Region.Count.isZero(); + CountedBranchRegions.back().FalseFolded = Region.FalseCount.isZero(); return; } if (CountedRegions.empty()) diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 4e4b75d92858b0..6fc6ea272479ef 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1679,6 +1679,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { return Name == "fabs" || Name == "fabsf" || Name == "floor" || Name == "floorf" || Name == "fmod" || Name == "fmodf"; + case 'i': + return Name == "ilogb" || Name == "ilogbf"; case 'l': return Name == "log" || Name == "logf" || Name == "logl" || Name == "log2" || Name == "log2f" || Name == "log10" || @@ -2133,7 +2135,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, } #endif - if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) + if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy() && + !Ty->isIntegerTy()) return nullptr; // Use internal versions of these intrinsics. @@ -2393,6 +2396,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, // TODO: What about hosts that lack a C99 library? return ConstantFoldFP(log10, APF, Ty); break; + case LibFunc_ilogb: + case LibFunc_ilogbf: + if (!APF.isZero() && TLI->has(Func)) + return ConstantInt::get(Ty, ilogb(APF), true); + break; case LibFunc_logb: case LibFunc_logbf: if (!APF.isZero() && TLI->has(Func)) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index c713371da81e40..119e09187b9080 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -503,7 +503,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder { const auto &BranchParams = B->getBranchParams(); PosToID[I] = BranchParams.ID; CondLoc[I] = B->startLoc(); - Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero()); + Folded[I++] = (B->Count.isZero() || B->FalseCount.isZero()); } // Using Profile Bitmap from runtime, mark the executed test vectors. diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index ce0903b838aa8a..0d35bfb921dc79 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -539,10 +539,10 @@ class InnerLoopVectorizer { friend class LoopVectorizationPlanner; /// Set up the values of the IVs correctly when exiting the vector loop. - void fixupIVUsers(PHINode *OrigPhi, const InductionDescriptor &II, - Value *VectorTripCount, Value *EndValue, - BasicBlock *MiddleBlock, VPlan &Plan, - VPTransformState &State); + virtual void fixupIVUsers(PHINode *OrigPhi, const InductionDescriptor &II, + Value *VectorTripCount, Value *EndValue, + BasicBlock *MiddleBlock, VPlan &Plan, + VPTransformState &State); /// Iteratively sink the scalarized operands of a predicated instruction into /// the block that was created for it. @@ -770,6 +770,11 @@ class EpilogueVectorizerMainLoop : public InnerLoopAndEpilogueVectorizer { BasicBlock *emitIterationCountCheck(BasicBlock *Bypass, bool ForEpilogue); void printDebugTracesAtStart() override; void printDebugTracesAtEnd() override; + + void fixupIVUsers(PHINode *OrigPhi, const InductionDescriptor &II, + Value *VectorTripCount, Value *EndValue, + BasicBlock *MiddleBlock, VPlan &Plan, + VPTransformState &State) override {}; }; // A specialized derived class of inner loop vectorizer that performs @@ -8861,11 +8866,8 @@ static void addLiveOutsForFirstOrderRecurrences( ScalarPHVPBB = cast(MiddleVPBB->getSuccessors()[1]); } else if (ExitUsersToFix.empty()) { ScalarPHVPBB = cast(MiddleVPBB->getSingleSuccessor()); - } - if (!ScalarPHVPBB) { - assert(ExitUsersToFix.empty() && - "missed inserting extracts for exiting values"); - return; + } else { + llvm_unreachable("unsupported CFG in VPlan"); } VPBuilder ScalarPHBuilder(ScalarPHVPBB); diff --git a/llvm/test/Transforms/InstCombine/ilogb.ll b/llvm/test/Transforms/InstCombine/ilogb.ll new file mode 100644 index 00000000000000..e30791fe68e7b2 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/ilogb.ll @@ -0,0 +1,203 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i32 @ilogbf_const1() { +; CHECK-LABEL: define i32 @ilogbf_const1() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 7.000000e+00) +; CHECK-NEXT: ret i32 2 +; + %r = call i32 @ilogbf(float 7.000000e+00) + ret i32 %r +} + +define i32 @ilogb_const1() { +; CHECK-LABEL: define i32 @ilogb_const1() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -7.000000e+00) +; CHECK-NEXT: ret i32 2 +; + %r = call i32 @ilogb(double -7.000000e+00) + ret i32 %r +} + +define i32 @ilogbf_const2() { +; CHECK-LABEL: define i32 @ilogbf_const2() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 5.000000e-01) +; CHECK-NEXT: ret i32 -1 +; + %r = call i32 @ilogbf(float 5.000000e-01) + ret i32 %r +} + +define i32 @ilogb_const2() { +; CHECK-LABEL: define i32 @ilogb_const2() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -5.000000e-01) +; CHECK-NEXT: ret i32 -1 +; + %r = call i32 @ilogb(double -5.000000e-01) + ret i32 %r +} + +define i32 @ilogbf_zero() { +; CHECK-LABEL: define i32 @ilogbf_zero() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0.000000e+00) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float 0.000000e+00) + ret i32 %r +} + +define i32 @ilogb_zero() { +; CHECK-LABEL: define i32 @ilogb_zero() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0.000000e+00) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double 0.000000e+00) + ret i32 %r +} + +define i32 @ilogbf_neg_zero() { +; CHECK-LABEL: define i32 @ilogbf_neg_zero() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float -0.000000e+00) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float -0.000000e+00) + ret i32 %r +} + +define i32 @ilogb_neg_zero() { +; CHECK-LABEL: define i32 @ilogb_neg_zero() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -0.000000e+00) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double -0.000000e+00) + ret i32 %r +} + +define i32 @ilogbf_inf() { +; CHECK-LABEL: define i32 @ilogbf_inf() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF0000000000000) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float 0x7FF0000000000000) + ret i32 %r +} + +define i32 @ilogb_inf() { +; CHECK-LABEL: define i32 @ilogb_inf() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF0000000000000) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double 0x7FF0000000000000) + ret i32 %r +} + +define i32 @ilogbf_nan() { +; CHECK-LABEL: define i32 @ilogbf_nan() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF8000000000000) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float 0x7FF8000000000000) + ret i32 %r +} + +define i32 @ilogb_nan() { +; CHECK-LABEL: define i32 @ilogb_nan() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF8000000000000) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double 0x7FF8000000000000) + ret i32 %r +} + +define i32 @ilogbf_zero_readnone() { +; CHECK-LABEL: define i32 @ilogbf_zero_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0.000000e+00) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float 0.000000e+00) readnone + ret i32 %r +} + +define i32 @ilogb_zero_readnone() { +; CHECK-LABEL: define i32 @ilogb_zero_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0.000000e+00) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double 0.000000e+00) readnone + ret i32 %r +} + +define i32 @ilogbf_neg_zero_readnone() { +; CHECK-LABEL: define i32 @ilogbf_neg_zero_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float -0.000000e+00) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float -0.000000e+00) readnone + ret i32 %r +} + +define i32 @ilogb_neg_zero_readnone() { +; CHECK-LABEL: define i32 @ilogb_neg_zero_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -0.000000e+00) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double -0.000000e+00) readnone + ret i32 %r +} + +define i32 @ilogbf_inf_readnone() { +; CHECK-LABEL: define i32 @ilogbf_inf_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF0000000000000) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float 0x7FF0000000000000) readnone + ret i32 %r +} + +define i32 @ilogb_inf_readnone() { +; CHECK-LABEL: define i32 @ilogb_inf_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF0000000000000) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double 0x7FF0000000000000) readnone + ret i32 %r +} + +define i32 @ilogbf_nan_readnone() { +; CHECK-LABEL: define i32 @ilogbf_nan_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF8000000000000) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float 0x7FF8000000000000) readnone + ret i32 %r +} + +define i32 @ilogb_nan_readnone() { +; CHECK-LABEL: define i32 @ilogb_nan_readnone() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF8000000000000) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double 0x7FF8000000000000) readnone + ret i32 %r +} + +define i32 @ilogbf_poison() { +; CHECK-LABEL: define i32 @ilogbf_poison() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float poison) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogbf(float poison) + ret i32 %r +} + +define i32 @ilogb_poison() { +; CHECK-LABEL: define i32 @ilogb_poison() { +; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double poison) +; CHECK-NEXT: ret i32 [[R]] +; + %r = call i32 @ilogb(double poison) + ret i32 %r +} + +declare i32 @ilogbf(float) +declare i32 @ilogb(double) diff --git a/llvm/test/tools/llvm-cov/branch-c-general.test b/llvm/test/tools/llvm-cov/branch-c-general.test index 9b5889babde366..2fa99dfe61532e 100644 --- a/llvm/test/tools/llvm-cov/branch-c-general.test +++ b/llvm/test/tools/llvm-cov/branch-c-general.test @@ -47,7 +47,7 @@ // CHECK: Branch (103:9): [True: 9, False: 1] // CHECK: switches() -// CHECK: Branch (113:3): [True: 1, False: 0] +// CHECK: Branch (113:3): [True: 1, Folded] // CHECK: Branch (117:63): [True: 15, False: 0] // CHECK: Branch (119:5): [True: 1, False: 14] // CHECK: Branch (120:11): [True: 0, False: 1] @@ -57,7 +57,7 @@ // CHECK: Branch (126:11): [True: 3, False: 0] // CHECK: Branch (128:5): [True: 4, False: 11] // CHECK: Branch (129:11): [True: 4, False: 0] -// CHECK: Branch (131:7): [True: 4, False: 0] +// CHECK: Branch (131:7): [True: 4, Folded] // CHECK: Branch (132:13): [True: 4, False: 0] // CHECK: Branch (136:5): [True: 5, False: 10] // CHECK: Branch (137:11): [True: 1, False: 4] @@ -114,13 +114,13 @@ -// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover +// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover // REPORT-NEXT: --- // REPORT-NEXT: simple_loops 8 0 100.00% 9 0 100.00% 6 0 100.00% // REPORT-NEXT: conditionals 24 0 100.00% 15 0 100.00% 16 2 87.50% // REPORT-NEXT: early_exits 20 4 80.00% 25 2 92.00% 16 6 62.50% // REPORT-NEXT: jumps 39 12 69.23% 48 2 95.83% 26 9 65.38% -// REPORT-NEXT: switches 28 5 82.14% 38 4 89.47% 30 9 70.00% +// REPORT-NEXT: switches 28 5 82.14% 38 4 89.47% 28 7 75.00% // REPORT-NEXT: big_switch 25 1 96.00% 32 0 100.00% 30 6 80.00% // REPORT-NEXT: boolean_operators 16 0 100.00% 13 0 100.00% 22 2 90.91% // REPORT-NEXT: boolop_loops 19 0 100.00% 14 0 100.00% 16 2 87.50% @@ -129,12 +129,12 @@ // REPORT-NEXT: main 1 0 100.00% 16 0 100.00% 0 0 0.00% // REPORT-NEXT: c-general.c:static_func 4 0 100.00% 4 0 100.00% 2 0 100.00% // REPORT-NEXT: --- -// REPORT-NEXT: TOTAL 197 24 87.82% 234 8 96.58% 174 38 78.16% +// REPORT-NEXT: TOTAL 197 24 87.82% 234 8 96.58% 172 36 79.07% // Test file-level report. // RUN: llvm-profdata merge %S/Inputs/branch-c-general.proftext -o %t.profdata // RUN: llvm-cov report %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-c-general.c | FileCheck %s -check-prefix=FILEREPORT -// FILEREPORT: TOTAL{{.*}}174 38 78.16% +// FILEREPORT: TOTAL{{.*}}172 36 79.07% // Test color True/False output. // RUN: llvm-cov show --use-color --show-branches=count %S/Inputs/branch-c-general.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-c-general.c | FileCheck %s -check-prefix=USECOLOR @@ -161,6 +161,6 @@ // HTML-INDEX: // HTML-INDEX: 87.82% (173/197) // HTML-INDEX: -// HTML-INDEX: 78.16% (136/174) +// HTML-INDEX: 79.07% (136/172) // HTML-INDEX: // HTML-INDEX: Totals diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/llvm/tools/llvm-cov/CoverageExporterJson.cpp index 9a8c7c94f06124..4088c1b053aa8d 100644 --- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp +++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp @@ -125,7 +125,7 @@ json::Array renderRegions(ArrayRef Regions) { json::Array renderBranchRegions(ArrayRef Regions) { json::Array RegionArray; for (const auto &Region : Regions) - if (!Region.Folded) + if (!Region.TrueFolded || !Region.FalseFolded) RegionArray.push_back(renderBranch(Region)); return RegionArray; } diff --git a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp index ae8f556edb313b..d6b9367ae4c514 100644 --- a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp +++ b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp @@ -139,7 +139,7 @@ void renderBranchExecutionCounts(raw_ostream &OS, unsigned BranchIndex = 0; while (NextBranch != EndBranch && CurrentLine == NextBranch->LineStart) { - if (!NextBranch->Folded) { + if (!NextBranch->TrueFolded || !NextBranch->FalseFolded) { unsigned BC1 = NextBranch->ExecutionCount; unsigned BC2 = NextBranch->FalseExecutionCount; bool BranchNotExecuted = (BC1 == 0 && BC2 == 0); diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp index 4f150020ee3815..58e7918d392709 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp @@ -19,18 +19,18 @@ using namespace coverage; static void sumBranches(size_t &NumBranches, size_t &CoveredBranches, const ArrayRef &Branches) { for (const auto &BR : Branches) { - // Skip folded branches. - if (BR.Folded) - continue; - - // "True" Condition Branches. - ++NumBranches; - if (BR.ExecutionCount > 0) - ++CoveredBranches; - // "False" Condition Branches. - ++NumBranches; - if (BR.FalseExecutionCount > 0) - ++CoveredBranches; + if (!BR.TrueFolded) { + // "True" Condition Branches. + ++NumBranches; + if (BR.ExecutionCount > 0) + ++CoveredBranches; + } + if (!BR.FalseFolded) { + // "False" Condition Branches. + ++NumBranches; + if (BR.FalseExecutionCount > 0) + ++CoveredBranches; + } } } diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp index 6f4d327679d6b6..7421763dd7a427 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp @@ -1128,36 +1128,45 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV, "line-number") + "): ["; - if (R.Folded) { + if (R.TrueFolded && R.FalseFolded) { OS << "Folded - Ignored]\n"; continue; } // Display TrueCount or TruePercent. - std::string TrueColor = R.ExecutionCount ? "None" : "red branch"; + std::string TrueColor = + (R.TrueFolded || R.ExecutionCount ? "None" : "red branch"); std::string TrueCovClass = - (R.ExecutionCount > 0) ? "covered-line" : "uncovered-line"; - - OS << tag("span", "True", TrueColor); - OS << ": "; - if (getOptions().ShowBranchCounts) - OS << tag("span", formatCount(R.ExecutionCount), TrueCovClass) << ", "; - else - OS << format("%0.2f", TruePercent) << "%, "; + (R.TrueFolded || R.ExecutionCount > 0 ? "covered-line" + : "uncovered-line"); + + if (R.TrueFolded) + OS << "Folded, "; + else { + OS << tag("span", "True", TrueColor) << ": "; + if (getOptions().ShowBranchCounts) + OS << tag("span", formatCount(R.ExecutionCount), TrueCovClass) << ", "; + else + OS << format("%0.2f", TruePercent) << "%, "; + } // Display FalseCount or FalsePercent. - std::string FalseColor = R.FalseExecutionCount ? "None" : "red branch"; + std::string FalseColor = + (R.FalseFolded || R.FalseExecutionCount ? "None" : "red branch"); std::string FalseCovClass = - (R.FalseExecutionCount > 0) ? "covered-line" : "uncovered-line"; - - OS << tag("span", "False", FalseColor); - OS << ": "; - if (getOptions().ShowBranchCounts) - OS << tag("span", formatCount(R.FalseExecutionCount), FalseCovClass); - else - OS << format("%0.2f", FalsePercent) << "%"; - - OS << "]\n"; + (R.FalseFolded || R.FalseExecutionCount > 0 ? "covered-line" + : "uncovered-line"); + + if (R.FalseFolded) + OS << "Folded]\n"; + else { + OS << tag("span", "False", FalseColor) << ": "; + if (getOptions().ShowBranchCounts) + OS << tag("span", formatCount(R.FalseExecutionCount), FalseCovClass) + << "]\n"; + else + OS << format("%0.2f", FalsePercent) << "%]\n"; + } } OS << EndPre; OS << EndExpansionDiv; diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp index 8b93b592910b3d..444f33dac10837 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp @@ -309,31 +309,38 @@ void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV, renderLinePrefix(OS, ViewDepth); OS << " Branch (" << R.LineStart << ":" << R.ColumnStart << "): ["; - if (R.Folded) { + if (R.TrueFolded && R.FalseFolded) { OS << "Folded - Ignored]\n"; continue; } - colored_ostream(OS, raw_ostream::RED, - getOptions().Colors && !R.ExecutionCount, - /*Bold=*/false, /*BG=*/true) - << "True"; - - if (getOptions().ShowBranchCounts) - OS << ": " << formatCount(R.ExecutionCount) << ", "; - else - OS << ": " << format("%0.2f", TruePercent) << "%, "; - - colored_ostream(OS, raw_ostream::RED, - getOptions().Colors && !R.FalseExecutionCount, - /*Bold=*/false, /*BG=*/true) - << "False"; + if (R.TrueFolded) + OS << "Folded, "; + else { + colored_ostream(OS, raw_ostream::RED, + getOptions().Colors && !R.ExecutionCount, + /*Bold=*/false, /*BG=*/true) + << "True"; + + if (getOptions().ShowBranchCounts) + OS << ": " << formatCount(R.ExecutionCount) << ", "; + else + OS << ": " << format("%0.2f", TruePercent) << "%, "; + } - if (getOptions().ShowBranchCounts) - OS << ": " << formatCount(R.FalseExecutionCount); - else - OS << ": " << format("%0.2f", FalsePercent) << "%"; - OS << "]\n"; + if (R.FalseFolded) + OS << "Folded]\n"; + else { + colored_ostream(OS, raw_ostream::RED, + getOptions().Colors && !R.FalseExecutionCount, + /*Bold=*/false, /*BG=*/true) + << "False"; + + if (getOptions().ShowBranchCounts) + OS << ": " << formatCount(R.FalseExecutionCount) << "]\n"; + else + OS << ": " << format("%0.2f", FalsePercent) << "%]\n"; + } } } diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 45313200d4f0b9..626539cb7bde42 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -948,7 +948,7 @@ def MapInfoOp : OpenMP_Op<"map.info", [AttrSizedOperandSegments]> { objects (e.g. derived types or classes), indicates the bounds to be copied of the variable. When it's an array slice it is in rank order where rank 0 is the inner-most dimension. - - 'map_clauses': OpenMP map type for this map capture, for example: from, to and + - 'map_type': OpenMP map type for this map capture, for example: from, to and always. It's a bitfield composed of the OpenMP runtime flags stored in OpenMPOffloadMappingFlags. - 'map_capture_type': Capture type for the variable e.g. this, byref, byvalue, byvla