Incremental Coverage Report base: HEAD~1 → head: 093fc902e3a5
Changed Files 4
Diff Lines 186
Exec Lines 109
Covered Lines 0
Branches 0/69
Line Cov. 0.0%
Branch Cov. 0.0%
Line Coverage 0.0%
0%
Branch Coverage 0.0%
0%
Commits in Range (1)
Coverage Legend
Line Covered
Line Uncovered
Branch Covered
Branch Partial
Branch Uncovered
Non-executable
Changed Files Overview
Summary of all files modified in this commit
File Total Lines Changed Covered Uncovered Incremental % Status Branch %
[F] llvm/include/llvm/Transforms/Scalar/CJFillMetadata.h 290 11 0 0 100.0% PASS 100.0%
[F] llvm/lib/Transforms/Scalar/CJFillMetadata.cpp 1801 153 0 109 0.0% FAIL 0.0%
[F] llvm/lib/Passes/PassBuilder.cpp 2013 4 0 0 100.0% PASS 100.0%
[F] llvm/lib/Passes/PassBuilderPipelines.cpp 2139 18 0 0 100.0% PASS 100.0%
[F] llvm/include/llvm/Transforms/Scalar/CJFillMetadata.h 11 lines | 0 covered | 0 uncovered | 0/0 branches | 100.0%
⋮ 260 lines hidden ⋮
261
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) const;
262
};
263
264
// CJDisableImportLibReflection strips import-lib reflection at LTO post-link
265
// under --disable-reflection: clears the TF_REFLECTION flag on each
266
// TypeInfo/TypeTemplate, rewrites oversized reflect structs to a small .dbg
267
// global (enum keeps ctorInfo/modifier/ctorCnt, class keeps fieldNames), keeps
268
// already-minimal/unsupported reflect operands unchanged, and erases the
269
// now-unreferenced reflect globals.
270
struct CJDisableImportLibReflection
271
: public PassInfoMixin<CJDisableImportLibReflection> {
272
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) const;
273
};
274
275
constexpr uint32_t ArrayHeadSize = 16;
276
constexpr uint32_t ObjectHeadSize = 8;
277
constexpr uint32_t SyncSize = 168;
⋮ 13 lines hidden ⋮
[F] llvm/lib/Transforms/Scalar/CJFillMetadata.cpp 153 lines | 0 covered | 109 uncovered | 0/69 branches | 0.0%
⋮ 1624 lines hidden ⋮
1625
return PreservedAnalyses::all();
1626
}
1627
1628
namespace {
1629
1630
// Copy the debug fields of a reflect struct into a small .dbg global.
1631
// Enum reflects keep operands [0..2] (ctorInfo/modifier/ctorCnt), non-enum
1632
// reflects keep operand [0] only. We only rewrite when that compact form would
1633
// actually shrink the payload; otherwise the caller keeps the original
1634
// reflection operand unchanged.
1635
// IsEnum comes from the owner's type byte, not operand count — enum reflects
1636
// can grow to 15+ operands, so field count is not a reliable discriminator.
1637
GlobalVariable *downgradeReflectGlobal(GlobalVariable &ReflectGV, bool IsEnum) {
1638
if (!ReflectGV.hasInitializer())
1639
return nullptr;
1640
1641
auto *Init = dyn_cast<ConstantStruct>(ReflectGV.getInitializer());
1642
if (!Init)
1643
return nullptr;
1644
1645
unsigned NumOps = Init->getNumOperands();
1646
unsigned CopiedOps = IsEnum ? 3 : 1;
1647
if (NumOps <= CopiedOps)
1648
return nullptr;
1649
1650
SmallVector<Type *, 4> DebugTypes;
1651
SmallVector<Constant *, 4> DebugOps;
1652
for (unsigned I = 0; I < CopiedOps; ++I) {
1653
DebugTypes.push_back(Init->getOperand(I)->getType());
1654
DebugOps.push_back(Init->getOperand(I));
1655
}
1656
1657
auto *DebugST = StructType::get(ReflectGV.getContext(), DebugTypes);
1658
auto *DebugGV = new GlobalVariable(
1659
*ReflectGV.getParent(), DebugST, false, GlobalValue::InternalLinkage,
1660
ConstantStruct::get(DebugST, DebugOps), ReflectGV.getName() + ".dbg");
1661
DebugGV->copyAttributesFrom(&ReflectGV);
1662
return DebugGV;
1663
}
1664
1665
bool rewriteReflectionOperand(GlobalVariable &GV, unsigned FlagIdx,
1666
unsigned ReflectionIdx) {
1667
if (!GV.hasInitializer())
1668
return false;
1669
1670
auto *Init = dyn_cast<ConstantStruct>(GV.getInitializer());
1671
if (Init == nullptr || Init->getNumOperands() <= ReflectionIdx)
1672
return false;
1673
1674
auto *Flag = cast<ConstantInt>(Init->getOperand(FlagIdx));
1675
uint64_t NewFlag = Flag->getZExtValue() & ~TF_REFLECTION;
1676
1677
if (NewFlag == Flag->getZExtValue())
1678
return false;
1679
1680
SmallVector<Constant *, 0> Ops;
1681
Ops.reserve(Init->getNumOperands());
1682
for (unsigned I = 0; I < Init->getNumOperands(); ++I)
1683
Ops.push_back(cast<Constant>(Init->getOperand(I)));
1684
1685
Ops[FlagIdx] = ConstantInt::get(Flag->getType(), NewFlag);
1686
1687
auto *ReflectOp = Init->getOperand(ReflectionIdx);
1688
auto *CE = dyn_cast<ConstantExpr>(ReflectOp);
1689
if (CE && CE->getOpcode() == Instruction::BitCast) {
1690
bool IsEnum = false;
1691
unsigned TypeIdx = FlagIdx == CIT_FLAG ? CIT_TYPE : TT_TYPE;
1692
if (auto *TypeCI = dyn_cast<ConstantInt>(Init->getOperand(TypeIdx))) {
1693
int64_t Kind = TypeCI->getSExtValue();
1694
IsEnum = (Kind == TK_ENUM || Kind == TK_TEMP_ENUM);
1695
}
1696
1697
if (auto *ReflectGV = dyn_cast<GlobalVariable>(CE->getOperand(0))) {
1698
if (auto *DebugGV = downgradeReflectGlobal(*ReflectGV, IsEnum)) {
1699
Ops[ReflectionIdx] = ConstantExpr::getBitCast(DebugGV, CE->getType());
1700
}
1701
}
1702
}
1703
1704
GV.setInitializer(ConstantStruct::get(Init->getType(), Ops));
1705
return true;
1706
}
1707
1708
bool rewritePackageInfoPayload(GlobalVariable &GV) {
1709
if (!GV.hasInitializer())
1710
return false;
1711
1712
auto *Init = dyn_cast<ConstantStruct>(GV.getInitializer());
1713
if (Init == nullptr || Init->getNumOperands() < FPT_PTRS)
1714
return false;
1715
1716
// Clear only FPT_FLAG (PackageInfo::isVaild) to make package lookup fail; zeroing the counts
1717
// would misalign the runtime's GetPackageSize() stride walk over the packageInfos.
1718
auto *Flag = dyn_cast<ConstantInt>(Init->getOperand(FPT_FLAG));
1719
if (Flag == nullptr || Flag->isZero())
1720
return false;
1721
1722
SmallVector<Constant *, 0> Ops;
1723
Ops.reserve(Init->getNumOperands());
1724
for (unsigned I = 0; I < Init->getNumOperands(); ++I)
1725
Ops.push_back(cast<Constant>(Init->getOperand(I)));
1726
1727
Ops[FPT_FLAG] = ConstantInt::get(Flag->getType(), 0);
1728
GV.setInitializer(ConstantStruct::get(Init->getType(), Ops));
1729
return true;
1730
}
1731
1732
// Erase reflect globals left unreferenced by the rewrite (needed at FullLTO
1733
// -O0, where no GlobalDCE follows). Scope: internal + isCJReflectGV() + no
1734
// uses; fixpoint collects chains. .dbg/fieldNames stay referenced and never
1735
// touched.
1736
void eraseReflectGlobals(Module &M) {
1737
bool RoundChanged = true;
1738
while (RoundChanged) {
1739
RoundChanged = false;
1740
SmallVector<GlobalVariable *, 16> ToErase;
1741
for (auto &GV : M.globals()) {
1742
if (GV.isDeclaration() || !GV.isCJReflectGV() ||
1743
!GlobalValue::isInternalLinkage(GV.getLinkage()))
1744
continue;
1745
// The rewrite detaches the old TI/TT initializer constant, whose nested
1746
// constant exprs still count as uses; drop them so use_empty() is accurate.
1747
GV.removeDeadConstantUsers();
1748
if (!GV.use_empty())
1749
continue;
1750
ToErase.push_back(&GV);
1751
}
1752
for (auto *GV : ToErase) {
1753
GV->eraseFromParent();
1754
RoundChanged = true;
1755
}
1756
}
1757
}
1758
} // namespace
1759
1760
PreservedAnalyses
1761
CJDisableImportLibReflection::run(Module &M, ModuleAnalysisManager &) const {
1762
bool Changed = false;
1763
for (auto &GV : M.globals()) {
1764
if (GV.isCJTypeInfo()) {
1765
Changed |= rewriteReflectionOperand(GV, CIT_FLAG, CIT_REFLECTION);
1766
} else if (GV.isCJTypeTemplate()) {
1767
Changed |= rewriteReflectionOperand(GV, TT_FLAG, TT_REFLECTION);
1768
} else if (GV.isCJReflectPkgInfo()) {
1769
Changed |= rewritePackageInfoPayload(GV);
1770
}
1771
}
1772
// Self-erase dead reflection globals; harmless where GlobalDCE follows.
1773
// Nothing becomes dead unless a rewrite happened, so skip the scan otherwise.
1774
if (Changed) {
1775
eraseReflectGlobals(M);
1776
return PreservedAnalyses::none();
1777
}
1778
return PreservedAnalyses::all();
1779
}
1780
1781
namespace {
1782
class CJFillMetadataLegacyPass : public ModulePass {
1783
public:
⋮ 18 lines hidden ⋮
[F] llvm/lib/Passes/PassBuilder.cpp 4 lines | 0 covered | 0 uncovered | 0/0 branches | 100.0%
⋮ 326 lines hidden ⋮
327
EnableCJPtrAuthBackwardCFI("cj-ptrauth-backward-cfi",
328
cl::desc("Cangjie PtrAuth-based backward CFI"),
329
cl::NotHidden, cl::init(false));
330
cl::opt<bool> DisableCJLTOReflection("cj-disable-lto-reflection", cl::Hidden,
331
cl::init(false),
332
cl::desc("Disable reflection metadata in"
333
" cangjie LTO pipelines"));
334
335
namespace llvm {
336
cl::opt<bool> PrintPipelinePasses(
⋮ 1677 lines hidden ⋮
[F] llvm/lib/Passes/PassBuilderPipelines.cpp 18 lines | 0 covered | 0 uncovered | 0/0 branches | 100.0%
⋮ 202 lines hidden ⋮
203
extern cl::opt<int> CountedLoopTripWidth;
204
extern cl::opt<bool> CangjieLTOPreOpt;
205
extern cl::opt<bool> EnableCJPtrAuthBackwardCFI;
206
extern cl::opt<bool> DisableCJLTOReflection;
207
208
PipelineTuningOptions::PipelineTuningOptions() {
209
LoopInterleaving = true;
⋮ 1289 lines hidden ⋮
1499
else if (LTOPreLink)
1500
LTOPhase = ThinOrFullLTOPhase::FullLTOPreLink;
1501
1502
// Import-lib reflection is trimmed at post-link by CJDisableImportLibReflection;
1503
// the main package already has TF_REFLECTION=0 under --disable-reflection.
1504
// Add the core simplification pipeline.
1505
MPM.addPass(buildModuleSimplificationPipeline(Level, LTOPhase));
1506
⋮ 109 lines hidden ⋮
1616
// with ThinLTO in order to avoid leaving undefined references to dead
1617
// globals in the object file.
1618
MPM.addPass(EliminateAvailableExternallyPass());
1619
if (CJPipeline && DisableCJLTOReflection)
1620
MPM.addPass(CJDisableImportLibReflection());
1621
MPM.addPass(GlobalDCEPass());
1622
return MPM;
1623
}
⋮ 1 lines hidden ⋮
1625
// Force any function attributes we want the rest of the pipeline to observe.
1626
MPM.addPass(ForceFunctionAttrsPass());
1627
1628
if (CJPipeline && DisableCJLTOReflection) {
1629
MPM.addPass(CJDisableImportLibReflection());
1630
}
1631
1632
// Add the core simplification pipeline.
1633
MPM.addPass(buildModuleSimplificationPipeline(
1634
Level, ThinOrFullLTOPhase::ThinLTOPostLink));
⋮ 61 lines hidden ⋮
1696
// Emit annotation remarks.
1697
addAnnotationRemarksPass(MPM);
1698
1699
if (CJPipeline && DisableCJLTOReflection) {
1700
MPM.addPass(CJDisableImportLibReflection());
1701
// No GlobalDCE at -O0; the pass self-erases dead reflection globals.
1702
}
1703
1704
return MPM;
1705
}
1706
⋮ 8 lines hidden ⋮
1715
ThinOrFullLTOPhase::FullLTOPostLink);
1716
}
1717
1718
if (CJPipeline && DisableCJLTOReflection) {
1719
MPM.addPass(CJDisableImportLibReflection());
1720
}
1721
1722
if (PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) {
1723
// Load sample profile before running the LTO optimization pipeline.
1724
MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile,
⋮ 415 lines hidden ⋮