From 00d5f11881f3d47f95a57f48795fc984211d467f Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Wed, 13 Nov 2024 14:19:51 +0300 Subject: [PATCH 1/6] initial commit --- clang/include/clang/CIR/MissingFeatures.h | 3 -- .../TargetLowering/LowerFunction.cpp | 37 +++++++++++++++++- .../TargetLowering/RecordLayoutBuilder.cpp | 38 ++++++++++++++++--- .../AArch64/aarch64-cc-structs.c | 29 ++++++++++++++ 4 files changed, 98 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index b25c5e07f9f0..e0810f3ba5c6 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -401,9 +401,6 @@ struct MissingFeatures { // specs. We should make it always present. static bool makeTripleAlwaysPresent() { return false; } - // This Itanium bit is currently being skipped in cir. - static bool itaniumRecordLayoutBuilderFinishLayout() { return false; } - static bool mustProgress() { return false; } }; diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index d2a7e83e7020..c45c87bf31d9 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -278,6 +278,40 @@ cir::AllocaOp findAlloca(mlir::Operation *op) { return {}; } +mlir::Value createNonPrimitiveValue(mlir::Value Src, mlir::Type Ty, + LowerFunction &LF) { + if (auto Load = mlir::dyn_cast(Src.getDefiningOp())) { + auto &bld = LF.getRewriter(); + auto Addr = Load.getAddr(); + + auto oldAlloca = mlir::dyn_cast(Addr.getDefiningOp()); + auto Alloca = bld.create( + Src.getLoc(), bld.getType(Ty), Ty, + /*name=*/llvm::StringRef(""), oldAlloca.getAlignmentAttr()); + + auto Size = LF.LM.getDataLayout().getTypeStoreSize(Ty); + auto uInt64Ty = IntType::get(bld.getContext(), 64, false); + auto SizeVal = bld.create(Src.getLoc(), uInt64Ty, + IntAttr::get(uInt64Ty, Size)); + + auto VoidTy = VoidType::get(bld.getContext()); + auto VoidPtrTy = PointerType::get(bld.getContext(), VoidTy); + + auto SrcVoidPtr = + bld.create(Src.getLoc(), VoidPtrTy, CastKind::bitcast, Addr); + auto DestVoidPtr = + bld.create(Src.getLoc(), VoidPtrTy, CastKind::bitcast, Alloca); + + bld.create(Src.getLoc(), DestVoidPtr, SrcVoidPtr, SizeVal); + + auto newLoad = bld.create(Src.getLoc(), Alloca.getResult()); + bld.replaceAllOpUsesWith(Load, newLoad); + + return newLoad; + } + return {}; +} + /// After the calling convention is lowered, an ABI-agnostic type might have to /// be loaded back to its ABI-aware couterpart so it may be returned. If they /// differ, we have to do a coerced load. A coerced load, which means to load a @@ -301,7 +335,8 @@ mlir::Value castReturnValue(mlir::Value Src, mlir::Type Ty, LowerFunction &LF) { auto intTy = mlir::dyn_cast(Ty); if (intTy && !intTy.isPrimitive()) - cir_cconv_unreachable("non-primitive types NYI"); + return createNonPrimitiveValue(Src, Ty, LF); + llvm::TypeSize DstSize = LF.LM.getDataLayout().getTypeAllocSize(Ty); // FIXME(cir): Do we need the EnterStructPointerForCoercedAccess routine here? diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp index 627f3b048817..d7673d09bad0 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp @@ -223,6 +223,10 @@ class ItaniumRecordLayoutBuilder { /// Initialize record layout for the given record decl. void initializeLayout(const Type Ty); + /// FinishLayout - Finalize record layout. Adjust record size based on the + /// alignment. + void finishLayout(const StructType D); + uint64_t getDataSizeInBits() const { return DataSize; } void setDataSize(clang::CharUnits NewSize) { @@ -243,8 +247,7 @@ void ItaniumRecordLayoutBuilder::layout(const StructType RT) { // FIXME(cir): Handle virtual-related layouts. cir_cconv_assert(!cir::MissingFeatures::getCXXRecordBases()); - cir_cconv_assert( - !cir::MissingFeatures::itaniumRecordLayoutBuilderFinishLayout()); + finishLayout(RT); } void ItaniumRecordLayoutBuilder::initializeLayout(const mlir::Type Ty) { @@ -478,6 +481,31 @@ void ItaniumRecordLayoutBuilder::layoutFields(const StructType D) { } } +void ItaniumRecordLayoutBuilder::finishLayout(const StructType D) { + // If we have any remaining field tail padding, include that in the overall + // size. + setSize(std::max(getSizeInBits(), (uint64_t)Context.toBits(PaddedFieldSize))); + + // Finally, round the size of the record up to the alignment of the + // record itself. + uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit; + uint64_t UnpackedSizeInBits = + llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment)); + + uint64_t RoundedSize = llvm::alignTo( + getSizeInBits(), + Context.toBits(!Context.getTargetInfo().defaultsToAIXPowerAlignment() + ? Alignment + : PreferredAlignment)); + + if (UseExternalLayout) { + cir_cconv_unreachable("NYI"); + } + + // Set the size to the final size. + setSize(RoundedSize); +} + void ItaniumRecordLayoutBuilder::UpdateAlignment( clang::CharUnits NewAlignment, clang::CharUnits UnpackedNewAlignment, clang::CharUnits PreferredNewAlignment) { @@ -522,12 +550,12 @@ void ItaniumRecordLayoutBuilder::checkFieldPadding( // Warn if padding was introduced to the struct/class. if (!IsUnion && Offset > UnpaddedOffset) { unsigned PadSize = Offset - UnpaddedOffset; - // bool InBits = true; + bool InBits = true; if (PadSize % CharBitNum == 0) { PadSize = PadSize / CharBitNum; - // InBits = false; + InBits = false; } - cir_cconv_assert(cir::MissingFeatures::bitFieldPaddingDiagnostics()); + cir_cconv_assert(!cir::MissingFeatures::bitFieldPaddingDiagnostics()); } if (isPacked && Offset != UnpackedOffset) { HasPackedField = true; diff --git a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c index eb1899840713..b816d01fc74e 100644 --- a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c +++ b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c @@ -152,3 +152,32 @@ void pass_eq_128(EQ_128 s) {} // LLVM: store ptr %0, ptr %[[#V1]], align 8 // LLVM: %[[#V2:]] = load ptr, ptr %[[#V1]], align 8 void pass_gt_128(GT_128 s) {} + +typedef struct { + uint8_t a; + uint16_t b; + uint8_t c; +} S_PAD; + +// CHECK: cir.func {{.*@ret_s_pad}}() -> !u48i +// CHECK: %[[#V0:]] = cir.alloca !ty_S_PAD, !cir.ptr, ["__retval"] {alignment = 2 : i64} +// CHECK: %[[#V1:]] = cir.load %[[#V0]] : !cir.ptr, !ty_S_PAD +// CHECK: %[[#V2:]] = cir.alloca !u48i, !cir.ptr, [""] {alignment = 2 : i64} +// CHECK: %[[#V3:]] = cir.const #cir.int<6> : !u64i +// CHECK: %[[#V4:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr) +// CHECK: %[[#V5:]] = cir.cast(bitcast, %[[#V2:]] : !cir.ptr), !cir.ptr +// CHECK: cir.libc.memcpy %[[#V3]] bytes from %[[#V4]] to %[[#V5]] : !u64i, !cir.ptr +// CHECK: %[[#V6:]] = cir.load %[[#V2]] : !cir.ptr +// CHECK: cir.return %[[#V6]] + +// LLVM: i48 @ret_s_pad() +// LLVM: %[[#V1:]] = alloca %struct.S_PAD, i64 1, align 2 +// LLVM: %[[#V2:]] = load %struct.S_PAD, ptr %[[#V1]], align 2 +// LLVM: %[[#V3:]] = alloca i48, i64 1, align 2 +// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[#V3]], ptr %[[#V1]], i64 6, i1 false) +// LLVM: %[[#V4:]] = load i48, ptr %[[#V3]] +// LLVM: ret i48 %[[#V4]] +S_PAD ret_s_pad() { + S_PAD s; + return s; +} \ No newline at end of file From ce67cb9d274896aa747b28cfb7ffd1e23077b5b8 Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Wed, 13 Nov 2024 15:08:03 +0300 Subject: [PATCH 2/6] cleanup --- .../Transforms/TargetLowering/LowerFunction.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index c45c87bf31d9..18f0cd444116 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -278,8 +278,10 @@ cir::AllocaOp findAlloca(mlir::Operation *op) { return {}; } -mlir::Value createNonPrimitiveValue(mlir::Value Src, mlir::Type Ty, - LowerFunction &LF) { +/// Creates a coerced value from \param Src having a type of \param Ty which is +/// a non primitive type +mlir::Value createCoercedNonPrimitive(mlir::Value Src, mlir::Type Ty, + LowerFunction &LF) { if (auto Load = mlir::dyn_cast(Src.getDefiningOp())) { auto &bld = LF.getRewriter(); auto Addr = Load.getAddr(); @@ -309,7 +311,8 @@ mlir::Value createNonPrimitiveValue(mlir::Value Src, mlir::Type Ty, return newLoad; } - return {}; + + cir_cconv_unreachable("NYI"); } /// After the calling convention is lowered, an ABI-agnostic type might have to @@ -335,7 +338,7 @@ mlir::Value castReturnValue(mlir::Value Src, mlir::Type Ty, LowerFunction &LF) { auto intTy = mlir::dyn_cast(Ty); if (intTy && !intTy.isPrimitive()) - return createNonPrimitiveValue(Src, Ty, LF); + return createCoercedNonPrimitive(Src, Ty, LF); llvm::TypeSize DstSize = LF.LM.getDataLayout().getTypeAllocSize(Ty); From 835ee1ce060d3419f28f7a975ddaa89355b792be Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Thu, 14 Nov 2024 11:46:46 +0300 Subject: [PATCH 3/6] merge test properly --- .../AArch64/aarch64-cc-structs.c | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c index b3ee78f223fa..1f47cac4617c 100644 --- a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c +++ b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c @@ -153,6 +153,22 @@ void pass_eq_128(EQ_128 s) {} // LLVM: %[[#V2:]] = load ptr, ptr %[[#V1]], align 8 void pass_gt_128(GT_128 s) {} +// CHECK: cir.func @passS(%arg0: !cir.array +// CHECK: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr, [""] {alignment = 4 : i64} +// CHECK: %[[#V1:]] = cir.alloca !cir.array, !cir.ptr>, ["tmp"] {alignment = 8 : i64} +// CHECK: cir.store %arg0, %[[#V1]] : !cir.array, !cir.ptr> +// CHECK: %[[#V2:]] = cir.cast(bitcast, %[[#V1]] : !cir.ptr>), !cir.ptr +// CHECK: %[[#V3:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr +// CHECK: %[[#V4:]] = cir.const #cir.int<12> : !u64i +// CHECK: cir.libc.memcpy %[[#V4]] bytes from %[[#V2]] to %[[#V3]] : !u64i, !cir.ptr -> !cir.ptr + +// LLVM: void @passS([2 x i64] %[[#ARG:]]) +// LLVM: %[[#V1:]] = alloca %struct.S, i64 1, align 4 +// LLVM: %[[#V2:]] = alloca [2 x i64], i64 1, align 8 +// LLVM: store [2 x i64] %[[#ARG]], ptr %[[#V2]], align 8 +// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[#V1]], ptr %[[#V2]], i64 12, i1 false) +void passS(S s) {} + typedef struct { uint8_t a; uint16_t b; @@ -180,19 +196,4 @@ typedef struct { S_PAD ret_s_pad() { S_PAD s; return s; -} -// CHECK: cir.func @passS(%arg0: !cir.array -// CHECK: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr, [""] {alignment = 4 : i64} -// CHECK: %[[#V1:]] = cir.alloca !cir.array, !cir.ptr>, ["tmp"] {alignment = 8 : i64} -// CHECK: cir.store %arg0, %[[#V1]] : !cir.array, !cir.ptr> -// CHECK: %[[#V2:]] = cir.cast(bitcast, %[[#V1]] : !cir.ptr>), !cir.ptr -// CHECK: %[[#V3:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr -// CHECK: %[[#V4:]] = cir.const #cir.int<12> : !u64i -// CHECK: cir.libc.memcpy %[[#V4]] bytes from %[[#V2]] to %[[#V3]] : !u64i, !cir.ptr -> !cir.ptr - -// LLVM: void @passS([2 x i64] %[[#ARG:]]) -// LLVM: %[[#V1:]] = alloca %struct.S, i64 1, align 4 -// LLVM: %[[#V2:]] = alloca [2 x i64], i64 1, align 8 -// LLVM: store [2 x i64] %[[#ARG]], ptr %[[#V2]], align 8 -// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[#V1]], ptr %[[#V2]], i64 12, i1 false) -void passS(S s) {} +} \ No newline at end of file From 38b716bf125eb1e66c0ea6f3d5fbfc5b29f19185 Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Fri, 15 Nov 2024 11:01:08 +0300 Subject: [PATCH 4/6] use camel case --- .../Transforms/TargetLowering/RecordLayoutBuilder.cpp | 8 ++++---- .../CIR/CallConvLowering/AArch64/aarch64-cc-structs.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp index 8bfcad77958e..31eb5ff5490f 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp @@ -487,11 +487,11 @@ void ItaniumRecordLayoutBuilder::finishLayout(const StructType D) { // Finally, round the size of the record up to the alignment of the // record itself. - uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit; - uint64_t UnpackedSizeInBits = + uint64_t unpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit; + uint64_t unpackedSizeInBits = llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment)); - uint64_t RoundedSize = llvm::alignTo( + uint64_t roundedSize = llvm::alignTo( getSizeInBits(), Context.toBits(!Context.getTargetInfo().defaultsToAIXPowerAlignment() ? Alignment @@ -502,7 +502,7 @@ void ItaniumRecordLayoutBuilder::finishLayout(const StructType D) { } // Set the size to the final size. - setSize(RoundedSize); + setSize(roundedSize); } void ItaniumRecordLayoutBuilder::UpdateAlignment( diff --git a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c index 1f47cac4617c..717dfa172ced 100644 --- a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c +++ b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c @@ -196,4 +196,4 @@ typedef struct { S_PAD ret_s_pad() { S_PAD s; return s; -} \ No newline at end of file +} From 34b0fdb9ec972ef9f5340c656987f9fdbfa61537 Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Fri, 15 Nov 2024 11:15:09 +0300 Subject: [PATCH 5/6] more camel case --- .../Transforms/TargetLowering/RecordLayoutBuilder.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp index 31eb5ff5490f..db2af4ac9177 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/RecordLayoutBuilder.cpp @@ -548,11 +548,11 @@ void ItaniumRecordLayoutBuilder::checkFieldPadding( // Warn if padding was introduced to the struct/class. if (!IsUnion && Offset > UnpaddedOffset) { - unsigned PadSize = Offset - UnpaddedOffset; - bool InBits = true; - if (PadSize % CharBitNum == 0) { - PadSize = PadSize / CharBitNum; - InBits = false; + unsigned padSize = Offset - UnpaddedOffset; + bool inBits = true; + if (padSize % CharBitNum == 0) { + padSize = padSize / CharBitNum; + inBits = false; } cir_cconv_assert(!cir::MissingFeatures::bitFieldPaddingDiagnostics()); } From 5ba14748c1d1f47424e99887c0c7679e6b156b04 Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Fri, 15 Nov 2024 11:18:25 +0300 Subject: [PATCH 6/6] moree camel case --- .../Transforms/TargetLowering/LowerFunction.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index 38b208862aef..06242e52383a 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -347,23 +347,23 @@ mlir::Value emitAddressAtOffset(LowerFunction &LF, mlir::Value addr, return addr; } -/// Creates a coerced value from \param Src having a type of \param Ty which is +/// Creates a coerced value from \param src having a type of \param ty which is /// a non primitive type -mlir::Value createCoercedNonPrimitive(mlir::Value Src, mlir::Type Ty, +mlir::Value createCoercedNonPrimitive(mlir::Value src, mlir::Type ty, LowerFunction &LF) { - if (auto load = mlir::dyn_cast(Src.getDefiningOp())) { + if (auto load = mlir::dyn_cast(src.getDefiningOp())) { auto &bld = LF.getRewriter(); auto addr = load.getAddr(); auto oldAlloca = mlir::dyn_cast(addr.getDefiningOp()); auto alloca = bld.create( - Src.getLoc(), bld.getType(Ty), Ty, + src.getLoc(), bld.getType(ty), ty, /*name=*/llvm::StringRef(""), oldAlloca.getAlignmentAttr()); - auto tySize = LF.LM.getDataLayout().getTypeStoreSize(Ty); + auto tySize = LF.LM.getDataLayout().getTypeStoreSize(ty); createMemCpy(LF, alloca, addr, tySize.getFixedValue()); - auto newLoad = bld.create(Src.getLoc(), alloca.getResult()); + auto newLoad = bld.create(src.getLoc(), alloca.getResult()); bld.replaceAllOpUsesWith(load, newLoad); return newLoad;