[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2327,6 +2327,25 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_launder: return SemaBuiltinLaunder(*this, TheCall); + case Builtin::BI__builtin_clear_padding: { +const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); +const QualType PtrArgType = PtrArg->getType(); +if (!PtrArgType->isPointerType()) { + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << PtrArgType << "pointer" << 1 << 0 << 3 << 1 << PtrArgType + << "pointer"; + return ExprError(); +} +if (PtrArgType->getPointeeType().isConstQualified()) { + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_assign_const) + << TheCall->getSourceRange() << 5 /*ConstUnknown*/; + return ExprError(); +} +if (RequireCompleteType(PtrArg->getBeginLoc(), PtrArgType->getPointeeType(), +diag::err_typecheck_decl_incomplete_type)) + return ExprError(); +break; huixie90 wrote: yes. added https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2327,6 +2327,25 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_launder: return SemaBuiltinLaunder(*this, TheCall); + case Builtin::BI__builtin_clear_padding: { +const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); huixie90 wrote: removed https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); +Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } +} + +template +void ClearPaddingConstantArray(CodeGenFunction , Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, + size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); + ++ArrIndex) { + +QualType ElementQualType = AT->getElementType(); + +auto *ElementRecord = ElementQualType->getAsRecordDecl(); +if(!ElementRecord){ + std::cerr<< "\n\n null!" << std::endl; +} +auto ElementAlign =ElementRecord? +CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): +CGF.getContext().getTypeAlignInChars(ElementQualType); + + std::cerr<< "\n\n align: " << ElementAlign.getQuantity() << std::endl; + +// Value *Idx = CGF.Builder.getSize(0); +// Value *ArrayElement = CGF.Builder.CreateGEP(ElementType, Ptr, Idx); + +Address FieldElementAddr{Ptr, Type, ElementAlign}; + +auto Element = +CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); +auto *ElementType = CGF.ConvertTypeForMem(ElementQualType); +auto AllocSize = CGF.CGM.getModule().getDataLayout().getTypeAllocSize(ElementType); +std::cerr << "\n\n clearing array index! " << ArrIndex << std::endl; +RecursivelyClearPaddingImpl(CGF, Element.getPointer(), ElementQualType, CurrentStartOffset + ArrIndex * AllocSize.getKnownMinValue(), RunningOffset, WriteZeroAtOffset); + } +} + +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, + size_t& RunningOffset, T&& WriteZeroAtOffset) { + + std::cerr << "\n\n zero padding before current ["<< RunningOffset << ", " << CurrentStartOffset<< ")"<< std::endl; + for (; RunningOffset < CurrentStartOffset; ++RunningOffset) { +WriteZeroAtOffset(RunningOffset); + } + auto Type = CGF.ConvertTypeForMem(Ty); + auto Size = CGF.CGM.getModule() +.getDataLayout() +.getTypeSizeInBits(Type) +.getKnownMinValue() / 8; + + if (auto *AT = dyn_cast(Ty)) { +ClearPaddingConstantArray(CGF, Ptr, Type, AT, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } + else if (auto *ST = dyn_cast(Type); ST && Ty->isRecordType()) { +ClearPaddingStruct(CGF, Ptr, Ty, ST, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else if (Ty->isAtomicType()) { +RecursivelyClearPaddingImpl(CGF, Ptr, Ty.getAtomicUnqualifiedType(), CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else { +std::cerr << "\n\n increment running offset from: " << RunningOffset << " to " << RunningOffset + Size << std::endl; +RunningOffset =
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); huixie90 wrote: no not at the moment. I need to figure out how to do it. https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); huixie90 wrote: thank you for suggestion. I tried to use both AST and LLVM layouts information. But please let me know if there is better way of doing this https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { huixie90 wrote: bases can be reordered to the end for virtual base. anyway, I sorted bases by offset now. for fields, IIRC, c++ requires them to be laid out in the same order added vtable pointers support. https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
https://github.com/huixie90 edited https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); +Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } +} + +template +void ClearPaddingConstantArray(CodeGenFunction , Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, + size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); + ++ArrIndex) { + +QualType ElementQualType = AT->getElementType(); + +auto *ElementRecord = ElementQualType->getAsRecordDecl(); +if(!ElementRecord){ + std::cerr<< "\n\n null!" << std::endl; +} +auto ElementAlign =ElementRecord? +CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): +CGF.getContext().getTypeAlignInChars(ElementQualType); + + std::cerr<< "\n\n align: " << ElementAlign.getQuantity() << std::endl; + +// Value *Idx = CGF.Builder.getSize(0); +// Value *ArrayElement = CGF.Builder.CreateGEP(ElementType, Ptr, Idx); + +Address FieldElementAddr{Ptr, Type, ElementAlign}; + +auto Element = +CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); +auto *ElementType = CGF.ConvertTypeForMem(ElementQualType); +auto AllocSize = CGF.CGM.getModule().getDataLayout().getTypeAllocSize(ElementType); +std::cerr << "\n\n clearing array index! " << ArrIndex << std::endl; +RecursivelyClearPaddingImpl(CGF, Element.getPointer(), ElementQualType, CurrentStartOffset + ArrIndex * AllocSize.getKnownMinValue(), RunningOffset, WriteZeroAtOffset); + } +} + +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, + size_t& RunningOffset, T&& WriteZeroAtOffset) { + + std::cerr << "\n\n zero padding before current ["<< RunningOffset << ", " << CurrentStartOffset<< ")"<< std::endl; + for (; RunningOffset < CurrentStartOffset; ++RunningOffset) { +WriteZeroAtOffset(RunningOffset); + } + auto Type = CGF.ConvertTypeForMem(Ty); + auto Size = CGF.CGM.getModule() +.getDataLayout() +.getTypeSizeInBits(Type) +.getKnownMinValue() / 8; + + if (auto *AT = dyn_cast(Ty)) { +ClearPaddingConstantArray(CGF, Ptr, Type, AT, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } + else if (auto *ST = dyn_cast(Type); ST && Ty->isRecordType()) { +ClearPaddingStruct(CGF, Ptr, Ty, ST, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else if (Ty->isAtomicType()) { +RecursivelyClearPaddingImpl(CGF, Ptr, Ty.getAtomicUnqualifiedType(), CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else { +std::cerr << "\n\n increment running offset from: " << RunningOffset << " to " << RunningOffset + Size << std::endl; +RunningOffset =
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -60,9 +60,14 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/TargetParser/AArch64TargetParser.h" #include "llvm/TargetParser/X86TargetParser.h" +#include #include #include + + +#include huixie90 wrote: changing it to llvm::dbgs() now. will remove it once the patch is ready https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; huixie90 wrote: Arrays are dealt with in a separate function https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
efriedma-quic wrote: Also, please fix the title so it isn't prefixed with "[libc++]"; the intent is for this to be used in libc++, but it's proposing a clang intrinsic. https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); +Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } +} + +template +void ClearPaddingConstantArray(CodeGenFunction , Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, + size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); + ++ArrIndex) { + +QualType ElementQualType = AT->getElementType(); + +auto *ElementRecord = ElementQualType->getAsRecordDecl(); +if(!ElementRecord){ + std::cerr<< "\n\n null!" << std::endl; +} +auto ElementAlign =ElementRecord? +CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): +CGF.getContext().getTypeAlignInChars(ElementQualType); + + std::cerr<< "\n\n align: " << ElementAlign.getQuantity() << std::endl; + +// Value *Idx = CGF.Builder.getSize(0); +// Value *ArrayElement = CGF.Builder.CreateGEP(ElementType, Ptr, Idx); + +Address FieldElementAddr{Ptr, Type, ElementAlign}; + +auto Element = +CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); +auto *ElementType = CGF.ConvertTypeForMem(ElementQualType); +auto AllocSize = CGF.CGM.getModule().getDataLayout().getTypeAllocSize(ElementType); +std::cerr << "\n\n clearing array index! " << ArrIndex << std::endl; +RecursivelyClearPaddingImpl(CGF, Element.getPointer(), ElementQualType, CurrentStartOffset + ArrIndex * AllocSize.getKnownMinValue(), RunningOffset, WriteZeroAtOffset); + } +} + +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, + size_t& RunningOffset, T&& WriteZeroAtOffset) { + + std::cerr << "\n\n zero padding before current ["<< RunningOffset << ", " << CurrentStartOffset<< ")"<< std::endl; + for (; RunningOffset < CurrentStartOffset; ++RunningOffset) { +WriteZeroAtOffset(RunningOffset); + } + auto Type = CGF.ConvertTypeForMem(Ty); + auto Size = CGF.CGM.getModule() +.getDataLayout() +.getTypeSizeInBits(Type) +.getKnownMinValue() / 8; + + if (auto *AT = dyn_cast(Ty)) { +ClearPaddingConstantArray(CGF, Ptr, Type, AT, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } + else if (auto *ST = dyn_cast(Type); ST && Ty->isRecordType()) { +ClearPaddingStruct(CGF, Ptr, Ty, ST, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else if (Ty->isAtomicType()) { +RecursivelyClearPaddingImpl(CGF, Ptr, Ty.getAtomicUnqualifiedType(), CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else { +std::cerr << "\n\n increment running offset from: " << RunningOffset << " to " << RunningOffset + Size << std::endl; +RunningOffset =
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -0,0 +1,556 @@ +// RUN: mkdir -p %t +// RUN: %clang++ %s -o %t/run +// RUN: %t/run efriedma-quic wrote: Tests that need to actually run generated code go into the test-suite repo. (I don't think that's really necessary here, though; if you're going to start using this in libc++, libc++ runtime tests will give us equivalent test coverage.) https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
https://github.com/efriedma-quic commented: Please clang-format changes. https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { efriedma-quic wrote: Is iterating over bases/fields like this actually guaranteed to return them in order of offset? Do we need to worry about vtable pointers? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -4315,6 +4453,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Ptr); } + case Builtin::BI__builtin_clear_padding: { +const Expr *Op = E->getArg(0); +Value *Address = EmitScalarExpr(Op); efriedma-quic wrote: EmitPointerWithAlignment()? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2327,6 +2327,25 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_launder: return SemaBuiltinLaunder(*this, TheCall); + case Builtin::BI__builtin_clear_padding: { +const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); +const QualType PtrArgType = PtrArg->getType(); +if (!PtrArgType->isPointerType()) { + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << PtrArgType << "pointer" << 1 << 0 << 3 << 1 << PtrArgType + << "pointer"; + return ExprError(); +} +if (PtrArgType->getPointeeType().isConstQualified()) { + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_assign_const) + << TheCall->getSourceRange() << 5 /*ConstUnknown*/; + return ExprError(); +} +if (RequireCompleteType(PtrArg->getBeginLoc(), PtrArgType->getPointeeType(), +diag::err_typecheck_decl_incomplete_type)) + return ExprError(); +break; efriedma-quic wrote: Do you need to check the number of arguments somewhere? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); +Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } +} + +template +void ClearPaddingConstantArray(CodeGenFunction , Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, + size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); + ++ArrIndex) { + +QualType ElementQualType = AT->getElementType(); + +auto *ElementRecord = ElementQualType->getAsRecordDecl(); +if(!ElementRecord){ + std::cerr<< "\n\n null!" << std::endl; +} +auto ElementAlign =ElementRecord? +CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): +CGF.getContext().getTypeAlignInChars(ElementQualType); + + std::cerr<< "\n\n align: " << ElementAlign.getQuantity() << std::endl; + +// Value *Idx = CGF.Builder.getSize(0); +// Value *ArrayElement = CGF.Builder.CreateGEP(ElementType, Ptr, Idx); + +Address FieldElementAddr{Ptr, Type, ElementAlign}; + +auto Element = +CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); +auto *ElementType = CGF.ConvertTypeForMem(ElementQualType); +auto AllocSize = CGF.CGM.getModule().getDataLayout().getTypeAllocSize(ElementType); +std::cerr << "\n\n clearing array index! " << ArrIndex << std::endl; +RecursivelyClearPaddingImpl(CGF, Element.getPointer(), ElementQualType, CurrentStartOffset + ArrIndex * AllocSize.getKnownMinValue(), RunningOffset, WriteZeroAtOffset); + } +} + +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, + size_t& RunningOffset, T&& WriteZeroAtOffset) { + + std::cerr << "\n\n zero padding before current ["<< RunningOffset << ", " << CurrentStartOffset<< ")"<< std::endl; + for (; RunningOffset < CurrentStartOffset; ++RunningOffset) { +WriteZeroAtOffset(RunningOffset); + } + auto Type = CGF.ConvertTypeForMem(Ty); + auto Size = CGF.CGM.getModule() +.getDataLayout() +.getTypeSizeInBits(Type) +.getKnownMinValue() / 8; + + if (auto *AT = dyn_cast(Ty)) { +ClearPaddingConstantArray(CGF, Ptr, Type, AT, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } + else if (auto *ST = dyn_cast(Type); ST && Ty->isRecordType()) { +ClearPaddingStruct(CGF, Ptr, Ty, ST, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else if (Ty->isAtomicType()) { +RecursivelyClearPaddingImpl(CGF, Ptr, Ty.getAtomicUnqualifiedType(), CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else { +std::cerr << "\n\n increment running offset from: " << RunningOffset << " to " << RunningOffset + Size << std::endl; +RunningOffset =
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2327,6 +2327,25 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_launder: return SemaBuiltinLaunder(*this, TheCall); + case Builtin::BI__builtin_clear_padding: { +const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); efriedma-quic wrote: Why IgnoreParenImpCasts()? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); efriedma-quic wrote: I'm a bit skeptical it's a good idea to rely on the LLVM StructLayout for this; lowering from a clang type to an LLVM type involves a bunch of transforms. Can we use information from the clang RecordLayout instead? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); +Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } +} + +template +void ClearPaddingConstantArray(CodeGenFunction , Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, + size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); + ++ArrIndex) { + +QualType ElementQualType = AT->getElementType(); + +auto *ElementRecord = ElementQualType->getAsRecordDecl(); +if(!ElementRecord){ + std::cerr<< "\n\n null!" << std::endl; +} +auto ElementAlign =ElementRecord? +CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): +CGF.getContext().getTypeAlignInChars(ElementQualType); + + std::cerr<< "\n\n align: " << ElementAlign.getQuantity() << std::endl; + +// Value *Idx = CGF.Builder.getSize(0); +// Value *ArrayElement = CGF.Builder.CreateGEP(ElementType, Ptr, Idx); + +Address FieldElementAddr{Ptr, Type, ElementAlign}; + +auto Element = +CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); +auto *ElementType = CGF.ConvertTypeForMem(ElementQualType); +auto AllocSize = CGF.CGM.getModule().getDataLayout().getTypeAllocSize(ElementType); +std::cerr << "\n\n clearing array index! " << ArrIndex << std::endl; +RecursivelyClearPaddingImpl(CGF, Element.getPointer(), ElementQualType, CurrentStartOffset + ArrIndex * AllocSize.getKnownMinValue(), RunningOffset, WriteZeroAtOffset); + } +} + +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, + size_t& RunningOffset, T&& WriteZeroAtOffset) { + + std::cerr << "\n\n zero padding before current ["<< RunningOffset << ", " << CurrentStartOffset<< ")"<< std::endl; + for (; RunningOffset < CurrentStartOffset; ++RunningOffset) { +WriteZeroAtOffset(RunningOffset); + } + auto Type = CGF.ConvertTypeForMem(Ty); + auto Size = CGF.CGM.getModule() +.getDataLayout() +.getTypeSizeInBits(Type) +.getKnownMinValue() / 8; + + if (auto *AT = dyn_cast(Ty)) { +ClearPaddingConstantArray(CGF, Ptr, Type, AT, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } + else if (auto *ST = dyn_cast(Type); ST && Ty->isRecordType()) { +ClearPaddingStruct(CGF, Ptr, Ty, ST, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else if (Ty->isAtomicType()) { +RecursivelyClearPaddingImpl(CGF, Ptr, Ty.getAtomicUnqualifiedType(), CurrentStartOffset, RunningOffset, WriteZeroAtOffset); + } else { +std::cerr << "\n\n increment running offset from: " << RunningOffset << " to " << RunningOffset + Size << std::endl; +RunningOffset =
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -60,9 +60,14 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/TargetParser/AArch64TargetParser.h" #include "llvm/TargetParser/X86TargetParser.h" +#include #include #include + + +#include efriedma-quic wrote: iostream is forbidden in LLVM code. If you think the debug prints are useful long-term, use llvm::dbgs(); otherwise, just delete them. https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2327,6 +2327,25 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_launder: return SemaBuiltinLaunder(*this, TheCall); + case Builtin::BI__builtin_clear_padding: { +const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); +const QualType PtrArgType = PtrArg->getType(); +if (!PtrArgType->isPointerType()) { + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_convert_incompatible) + << PtrArgType << "pointer" << 1 << 0 << 3 << 1 << PtrArgType + << "pointer"; + return ExprError(); +} +if (PtrArgType->getPointeeType().isConstQualified()) { + Diag(PtrArg->getBeginLoc(), diag::err_typecheck_assign_const) + << TheCall->getSourceRange() << 5 /*ConstUnknown*/; + return ExprError(); +} +if (RequireCompleteType(PtrArg->getBeginLoc(), PtrArgType->getPointeeType(), +diag::err_typecheck_decl_incomplete_type)) efriedma-quic wrote: Please define an error message that explains what's actually going wrong here, instead of reusing err_typecheck_decl_incomplete_type. (The other errors could also be improved a bit.) https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; efriedma-quic wrote: Is there supposed to be an early return here? How are we supposed to deal with arrays? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); efriedma-quic wrote: Do we need to handle bitfields? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -2456,6 +2461,139 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +template +void RecursivelyClearPaddingImpl(CodeGenFunction , Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset); + +template +void ClearPaddingStruct(CodeGenFunction , Value *Ptr, QualType Ty, StructType *ST, +size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + std::cerr << "\n struct! " << ST->getName().data() << std::endl; + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); + + auto R = dyn_cast(Ty->getAsRecordDecl()); + if(!R) { +std::cerr << "\n not a CXXRecordDecl" << std::endl; + + } + const ASTRecordLayout = CGF.getContext().getASTRecordLayout(R); + for (auto Base : R->bases()) { +std::cerr << "\n\n base!" << std::endl; +// Zero padding between base elements. +auto BaseRecord = cast(Base.getType()->getAsRecordDecl()); +auto Offset = static_cast( +ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); +// Recursively zero out base classes. +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); +Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } + + size_t NumFields = std::distance(R->field_begin(), R->field_end()); + auto CurrentField = R->field_begin(); + for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { +// Size needs to be in bytes so we can compare it later. +auto Offset = ASTLayout.getFieldOffset(I) / 8; +auto Index = SL->getElementContainingOffset(Offset); +Value *Idx = CGF.Builder.getSize(Index); +llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); +Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); +RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); + } +} + +template +void ClearPaddingConstantArray(CodeGenFunction , Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, + size_t CurrentStartOffset, size_t , T&& WriteZeroAtOffset) { + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); + ++ArrIndex) { + +QualType ElementQualType = AT->getElementType(); + +auto *ElementRecord = ElementQualType->getAsRecordDecl(); +if(!ElementRecord){ + std::cerr<< "\n\n null!" << std::endl; +} +auto ElementAlign =ElementRecord? +CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): efriedma-quic wrote: Why are we doing this different ways depending on whether we have a RecordType? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
https://github.com/efriedma-quic edited https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
ldionne wrote: @AaronBallman We're struggling a bit to find the right person to help review this -- do you know who would be a good candidate? Hui is very familiar with libc++ but he's less familiar with codegen, and I'm not very useful in that area of the project :-). https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
https://github.com/huixie90 ready_for_review https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -0,0 +1,556 @@ +// RUN: mkdir -p %t +// RUN: %clang++ %s -o %t/run +// RUN: %t/run ldionne wrote: I'm not sure if this is going to work on all configurations, for example when they cross compile. Is there a precedent for these kinds of runtime tests in the codegen tests? Probably worth making sure that this is how it's done elsewhere. https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
@@ -0,0 +1,556 @@ +// RUN: mkdir -p %t ldionne wrote: Are these files missing a license? https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)
https://github.com/huixie90 edited https://github.com/llvm/llvm-project/pull/75371 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits