|
63 | 63 | #include <optional> |
64 | 64 | #include <sstream> |
65 | 65 |
|
| 66 | + |
| 67 | + |
| 68 | +#include <iostream> |
| 69 | + |
66 | 70 | using namespace clang; |
67 | 71 | using namespace CodeGen; |
68 | 72 | using namespace llvm; |
@@ -2456,90 +2460,127 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, |
2456 | 2460 | return RValue::get(CGF->Builder.CreateCall(UBF, Args)); |
2457 | 2461 | } |
2458 | 2462 |
|
2459 | | -static void RecursivelyZeroNonValueBits(CodeGenFunction &CGF, Value *Ptr, |
2460 | | - QualType Ty) { |
2461 | | - auto *I8Ptr = CGF.Builder.CreateBitCast(Ptr, CGF.Int8PtrTy); |
2462 | | - auto *Zero = ConstantInt::get(CGF.Int8Ty, 0); |
2463 | | - auto WriteZeroAtOffset = [&](size_t Offset) { |
2464 | | - auto Index = ConstantInt::get(CGF.IntTy, Offset); |
2465 | | - auto Element = CGF.Builder.CreateGEP(I8Ptr, Index); |
2466 | | - CGF.Builder.CreateAlignedStore( |
2467 | | - Zero, Element, |
2468 | | - CharUnits::One().alignmentAtOffset(CharUnits::fromQuantity(Offset))); |
2469 | | - }; |
2470 | | - auto GetStructLayout = [&CGF](llvm::Type *Ty) { |
2471 | | - auto ST = cast<StructType>(Ty); |
2472 | | - return CGF.CGM.getModule().getDataLayout().getStructLayout(ST); |
2473 | | - }; |
| 2463 | +template <class T> |
| 2464 | +void RecursivelyClearPaddingImpl(CodeGenFunction &CGF, Value *Ptr, QualType Ty, size_t CurrentStartOffset, size_t &RunningOffset, T&& WriteZeroAtOffset); |
2474 | 2465 |
|
2475 | | - auto ST = cast<StructType>(Ptr->getType()->getPointerElementType()); |
2476 | | - auto SL = GetStructLayout(ST); |
| 2466 | +template <class T> |
| 2467 | +void ClearPaddingStruct(CodeGenFunction &CGF, Value *Ptr, QualType Ty, StructType *ST, |
| 2468 | + size_t CurrentStartOffset, size_t &RunningOffset, T&& WriteZeroAtOffset) { |
| 2469 | + std::cerr << "\n struct! " << ST->getName().data() << std::endl; |
| 2470 | + auto SL = CGF.CGM.getModule().getDataLayout().getStructLayout(ST); |
2477 | 2471 | auto R = cast<CXXRecordDecl>(Ty->getAsRecordDecl()); |
2478 | 2472 | const ASTRecordLayout &ASTLayout = CGF.getContext().getASTRecordLayout(R); |
2479 | | - size_t RunningOffset = 0; |
2480 | 2473 | for (auto Base : R->bases()) { |
| 2474 | + std::cerr << "\n\n base!" << std::endl; |
2481 | 2475 | // Zero padding between base elements. |
2482 | 2476 | auto BaseRecord = cast<CXXRecordDecl>(Base.getType()->getAsRecordDecl()); |
2483 | 2477 | auto Offset = static_cast<size_t>( |
2484 | 2478 | ASTLayout.getBaseClassOffset(BaseRecord).getQuantity()); |
2485 | | - for (; RunningOffset < Offset; ++RunningOffset) { |
2486 | | - WriteZeroAtOffset(RunningOffset); |
2487 | | - } |
2488 | 2479 | // Recursively zero out base classes. |
2489 | 2480 | auto Index = SL->getElementContainingOffset(Offset); |
2490 | | - auto BaseElement = CGF.Builder.CreateStructGEP(Ptr, Index); |
2491 | | - RecursivelyZeroNonValueBits(CGF, BaseElement, Base.getType()); |
2492 | | - // Use the LLVM StructType data layout so we pick up on packed types. |
2493 | | - auto SL = GetStructLayout(ST->getElementType(Index)); |
2494 | | - auto Size = SL->getSizeInBytes(); |
2495 | | - RunningOffset = Offset + Size; |
| 2481 | + Value *Idx = CGF.Builder.getSize(Index); |
| 2482 | + llvm::Type *CurrentBaseType = CGF.ConvertTypeForMem(Base.getType()); |
| 2483 | + Value *BaseElement = CGF.Builder.CreateGEP(CurrentBaseType, Ptr, Idx); |
| 2484 | + RecursivelyClearPaddingImpl(CGF, BaseElement, Base.getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); |
2496 | 2485 | } |
2497 | 2486 |
|
2498 | 2487 | size_t NumFields = std::distance(R->field_begin(), R->field_end()); |
2499 | 2488 | auto CurrentField = R->field_begin(); |
2500 | 2489 | for (size_t I = 0; I < NumFields; ++I, ++CurrentField) { |
2501 | 2490 | // Size needs to be in bytes so we can compare it later. |
2502 | 2491 | auto Offset = ASTLayout.getFieldOffset(I) / 8; |
2503 | | - for (; RunningOffset < Offset; ++RunningOffset) { |
2504 | | - WriteZeroAtOffset(RunningOffset); |
2505 | | - } |
2506 | | - |
2507 | 2492 | auto Index = SL->getElementContainingOffset(Offset); |
2508 | | - // If this field is an object, it may have non-zero padding. |
2509 | | - if (CurrentField->getType()->isRecordType()) { |
2510 | | - auto Element = CGF.Builder.CreateStructGEP(Ptr, Index); |
2511 | | - RecursivelyZeroNonValueBits(CGF, Element, CurrentField->getType()); |
2512 | | - } |
| 2493 | + Value *Idx = CGF.Builder.getSize(Index); |
| 2494 | + llvm::Type *CurrentFieldType = CGF.ConvertTypeForMem(CurrentField->getType()); |
| 2495 | + Value *Element = CGF.Builder.CreateGEP(CurrentFieldType, Ptr, Idx); |
| 2496 | + RecursivelyClearPaddingImpl(CGF, Element, CurrentField->getType(), CurrentStartOffset + Offset, RunningOffset, WriteZeroAtOffset); |
| 2497 | + } |
| 2498 | +} |
2513 | 2499 |
|
2514 | | - // TODO: warn if non-constant array type. |
2515 | | - if (isa<ConstantArrayType>(CurrentField->getType()) && |
2516 | | - CurrentField->getType() |
2517 | | - ->getArrayElementTypeNoTypeQual() |
2518 | | - ->isRecordType()) { |
2519 | | - auto FieldElement = CGF.Builder.CreateStructGEP(Ptr, Index); |
2520 | | - auto AT = cast<ConstantArrayType>(CurrentField->getType()); |
2521 | | - for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); |
2522 | | - ++ArrIndex) { |
2523 | | - auto ElementRecord = AT->getElementType()->getAsRecordDecl(); |
2524 | | - auto ElementAlign = |
2525 | | - CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(); |
2526 | | - Address FieldElementAddr{FieldElement, ElementAlign}; |
2527 | | - auto Element = |
2528 | | - CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); |
2529 | | - RecursivelyZeroNonValueBits(CGF, Element.getPointer(), |
2530 | | - AT->getElementType()); |
2531 | | - } |
| 2500 | +template <class T> |
| 2501 | +void ClearPaddingConstantArray(CodeGenFunction &CGF, Value *Ptr, llvm::Type *Type, ConstantArrayType const *AT, |
| 2502 | + size_t CurrentStartOffset, size_t &RunningOffset, T&& WriteZeroAtOffset) { |
| 2503 | + for (size_t ArrIndex = 0; ArrIndex < AT->getSize().getLimitedValue(); |
| 2504 | + ++ArrIndex) { |
| 2505 | + |
| 2506 | + QualType ElementQualType = AT->getElementType(); |
| 2507 | + |
| 2508 | + auto *ElementRecord = ElementQualType->getAsRecordDecl(); |
| 2509 | + if(!ElementRecord){ |
| 2510 | + std::cerr<< "\n\n null!" << std::endl; |
2532 | 2511 | } |
| 2512 | + auto ElementAlign =ElementRecord? |
| 2513 | + CGF.getContext().getASTRecordLayout(ElementRecord).getAlignment(): |
| 2514 | + CGF.getContext().getTypeAlignInChars(ElementQualType); |
| 2515 | + |
| 2516 | + std::cerr<< "\n\n align: " << ElementAlign.getQuantity() << std::endl; |
| 2517 | + |
| 2518 | + // Value *Idx = CGF.Builder.getSize(0); |
| 2519 | + // Value *ArrayElement = CGF.Builder.CreateGEP(ElementType, Ptr, Idx); |
2533 | 2520 |
|
2534 | | - auto Size = CGF.CGM.getModule() |
| 2521 | + Address FieldElementAddr{Ptr, Type, ElementAlign}; |
| 2522 | + |
| 2523 | + auto Element = |
| 2524 | + CGF.Builder.CreateConstArrayGEP(FieldElementAddr, ArrIndex); |
| 2525 | + auto *ElementType = CGF.ConvertTypeForMem(ElementQualType); |
| 2526 | + auto AllocSize = CGF.CGM.getModule().getDataLayout().getTypeAllocSize(ElementType); |
| 2527 | + std::cerr << "\n\n clearing array index! " << ArrIndex << std::endl; |
| 2528 | + RecursivelyClearPaddingImpl(CGF, Element.getPointer(), ElementQualType, CurrentStartOffset + ArrIndex * AllocSize.getKnownMinValue(), RunningOffset, WriteZeroAtOffset); |
| 2529 | + } |
| 2530 | +} |
| 2531 | + |
| 2532 | +template <class T> |
| 2533 | +void RecursivelyClearPaddingImpl(CodeGenFunction &CGF, Value *Ptr, QualType Ty, size_t CurrentStartOffset, |
| 2534 | + size_t& RunningOffset, T&& WriteZeroAtOffset) { |
| 2535 | + |
| 2536 | + std::cerr << "\n\n zero padding before current ["<< RunningOffset << ", " << CurrentStartOffset<< ")"<< std::endl; |
| 2537 | + for (; RunningOffset < CurrentStartOffset; ++RunningOffset) { |
| 2538 | + WriteZeroAtOffset(RunningOffset); |
| 2539 | + } |
| 2540 | + auto Type = CGF.ConvertTypeForMem(Ty); |
| 2541 | + auto Size = CGF.CGM.getModule() |
2535 | 2542 | .getDataLayout() |
2536 | | - .getTypeSizeInBits(ST->getElementType(Index)) |
2537 | | - .getKnownMinSize() / |
2538 | | - 8; |
2539 | | - RunningOffset = Offset + Size; |
| 2543 | + .getTypeSizeInBits(Type) |
| 2544 | + .getKnownMinValue() / 8; |
| 2545 | + |
| 2546 | + if (auto *AT = dyn_cast<ConstantArrayType>(Ty)) { |
| 2547 | + ClearPaddingConstantArray(CGF, Ptr, Type, AT, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); |
| 2548 | + } |
| 2549 | + else if (auto *ST = dyn_cast<StructType>(Type)) { |
| 2550 | + ClearPaddingStruct(CGF, Ptr, Ty, ST, CurrentStartOffset, RunningOffset, WriteZeroAtOffset); |
| 2551 | + } else { |
| 2552 | + std::cerr << "\n\n increment running offset from: " << RunningOffset << " to " << RunningOffset + Size << std::endl; |
| 2553 | + RunningOffset += Size; |
2540 | 2554 | } |
2541 | | - // Clear all bits after the last field. |
2542 | | - auto Size = SL->getSizeInBytes(); |
| 2555 | + |
| 2556 | +} |
| 2557 | + |
| 2558 | +static void RecursivelyZeroNonValueBits(CodeGenFunction &CGF, Value *Ptr, |
| 2559 | + QualType Ty) { |
| 2560 | + auto *I8Ptr = CGF.Builder.CreateBitCast(Ptr, CGF.Int8PtrTy); |
| 2561 | + auto *Zero = ConstantInt::get(CGF.Int8Ty, 0); |
| 2562 | + auto WriteZeroAtOffset = [&](size_t Offset) { |
| 2563 | + auto *Index = ConstantInt::get(CGF.IntTy, Offset); |
| 2564 | + auto *Element = CGF.Builder.CreateGEP(CGF.Int8Ty, I8Ptr, Index); |
| 2565 | + CGF.Builder.CreateAlignedStore( |
| 2566 | + Zero, Element, |
| 2567 | + CharUnits::One().alignmentAtOffset(CharUnits::fromQuantity(Offset))); |
| 2568 | + }; |
| 2569 | + |
| 2570 | + |
| 2571 | + size_t RunningOffset = 0; |
| 2572 | + |
| 2573 | + RecursivelyClearPaddingImpl(CGF, Ptr, Ty, 0, RunningOffset, WriteZeroAtOffset); |
| 2574 | + |
| 2575 | + // Clear tail padding |
| 2576 | + auto Type = CGF.ConvertTypeForMem(Ty); |
| 2577 | + |
| 2578 | + auto Size = CGF.CGM.getModule() |
| 2579 | + .getDataLayout() |
| 2580 | + .getTypeSizeInBits(Type) |
| 2581 | + .getKnownMinValue() / 8; |
| 2582 | + |
| 2583 | + std::cerr << "\n\n zero tail padding ["<< RunningOffset << ", " << Size << ")"<< std::endl; |
2543 | 2584 | for (; RunningOffset < Size; ++RunningOffset) { |
2544 | 2585 | WriteZeroAtOffset(RunningOffset); |
2545 | 2586 | } |
|
0 commit comments