[llvm-branch-commits] [clang] [Clang] Add pointer field protection feature. (PR #172119)
Peter Collingbourne via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 15 18:58:17 PST 2026
================
@@ -1310,21 +1310,92 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val, llvm::Type *Ty,
return Val;
}
+static std::vector<PFPField> findPFPCoercedFields(CodeGenFunction &CGF,
+ QualType SrcFETy) {
+ // Coercion directly through memory does not work if the structure has pointer
+ // field protection because the struct in registers has a different bit
+ // pattern to the struct in memory, so we must read the elements one by one
+ // and use them to form the coerced structure.
+ std::vector<PFPField> PFPFields;
+ CGF.getContext().findPFPFields(SrcFETy, CharUnits::Zero(), PFPFields,
+ /*IncludeVBases=*/true);
+
+ // Because we don't know which union member is selected, we don't modify the
+ // in-memory representation when passing a pointer that is part of a union
+ // field. This requires the union member to be trivially copyable;
+ // non-trivially-copyable unions cannot be directly passed by value.
+ llvm::erase_if(PFPFields, [](PFPField F) { return F.isWithinUnion; });
+ return PFPFields;
+}
+
+static llvm::Value *CreatePFPCoercedLoad(Address Src, QualType SrcFETy,
+ llvm::Type *Ty, CodeGenFunction &CGF) {
+ std::vector<PFPField> PFPFields = findPFPCoercedFields(CGF, SrcFETy);
+ if (PFPFields.empty())
+ return nullptr;
+
+ auto LoadCoercedField = [&](CharUnits Offset,
+ llvm::Type *FieldType) -> llvm::Value * {
+ if (!PFPFields.empty() && PFPFields[0].offset == Offset) {
+ auto fieldAddr = CGF.EmitAddressOfPFPField(Src, PFPFields[0]);
+ llvm::Value *FieldVal = CGF.Builder.CreateLoad(fieldAddr);
+ if (isa<llvm::IntegerType>(FieldType))
+ FieldVal = CGF.Builder.CreatePtrToInt(FieldVal, FieldType);
+ PFPFields.erase(PFPFields.begin());
+ return FieldVal;
+ }
+ auto FieldAddr =
+ CGF.Builder
+ .CreateConstInBoundsByteGEP(Src.withElementType(CGF.Int8Ty), Offset)
+ .withElementType(FieldType);
+ return CGF.Builder.CreateLoad(FieldAddr);
+ };
+ if (isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) {
+ auto Addr = CGF.EmitAddressOfPFPField(Src, PFPFields[0]);
+ llvm::Value *Val = CGF.Builder.CreateLoad(Addr);
+ if (isa<llvm::IntegerType>(Ty))
+ Val = CGF.Builder.CreatePtrToInt(Val, Ty);
+ return Val;
+ }
+ if (auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
+ auto *ET = AT->getElementType();
+ CharUnits wordSize = CGF.getContext().toCharUnitsFromBits(
+ CGF.CGM.getDataLayout().getTypeSizeInBits(ET));
+ CharUnits Offset = CharUnits::Zero();
+ llvm::Value *Val = llvm::PoisonValue::get(AT);
+ for (unsigned i = 0; i != AT->getNumElements(); ++i, Offset += wordSize)
+ Val = CGF.Builder.CreateInsertValue(Val, LoadCoercedField(Offset, ET), i);
+ return Val;
+ }
+ auto *ST = cast<llvm::StructType>(Ty);
+ llvm::Value *Val = llvm::PoisonValue::get(ST);
+ auto *SL = CGF.CGM.getDataLayout().getStructLayout(ST);
+ for (unsigned i = 0; i != ST->getNumElements(); ++i) {
----------------
pcc wrote:
Done (for the `ArrayType` case, because `StructType` was deleted)
https://github.com/llvm/llvm-project/pull/172119
More information about the llvm-branch-commits
mailing list