[clang] [libc++] Add builtin to clear padding bytes (prework for P0528R3) (PR #75371)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits

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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-06-14 Thread via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits

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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits

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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits


@@ -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)

2024-01-26 Thread Eli Friedman via cfe-commits

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)

2024-01-26 Thread Louis Dionne via cfe-commits

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)

2024-01-24 Thread via cfe-commits

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)

2024-01-19 Thread Louis Dionne via cfe-commits


@@ -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)

2024-01-19 Thread Louis Dionne via cfe-commits


@@ -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)

2023-12-21 Thread via cfe-commits

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