From ff088d9784a20ea565c37301b9febc0a1001d193 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Wed, 6 Nov 2024 11:31:06 +0300 Subject: [PATCH 1/5] [CIR][ABI][AArch64] support passing structs of size > 128 bits --- .../Transforms/TargetLowering/LowerCall.cpp | 2 ++ .../TargetLowering/LowerFunction.cpp | 25 +++++++++++++++++++ .../Transforms/TargetLowering/LowerTypes.cpp | 6 +++++ .../TargetLowering/Targets/AArch64.cpp | 2 +- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp index 54fe89838e82..26a032856c52 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp @@ -226,6 +226,8 @@ void LowerModule::constructAttributeList(StringRef Name, // Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign())); cir_cconv_assert(!::cir::MissingFeatures::noFPClass()); break; + case ABIArgInfo::Indirect: + break; default: cir_cconv_unreachable("Missing ABIArgInfo::Kind"); } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index 1b638411cc59..691b1ebf28c1 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -516,6 +516,31 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn, rewriter.eraseOp(argAlloca.getDefiningOp()); break; } + case ABIArgInfo::Indirect: { + auto AI = Fn.getArgument(FirstIRArg); + auto ptrTy = rewriter.getType(Arg.getType()); + ArgVals.push_back(AI); + + Value arg = SrcFn.getArgument(ArgNo); + cir_cconv_assert(arg.hasOneUse()); + auto *firstStore = *arg.user_begin(); + auto argAlloca = cast(firstStore).getAddr(); + + rewriter.setInsertionPoint(argAlloca.getDefiningOp()); + auto newAlloca = rewriter.create( + Fn.getLoc(), rewriter.getType(ptrTy), ptrTy, + /*name=*/StringRef(""), + /*alignment=*/rewriter.getI64IntegerAttr(8)); + + rewriter.create(newAlloca.getLoc(), AI, newAlloca.getResult()); + auto load = rewriter.create(newAlloca.getLoc(), newAlloca.getResult()); + + rewriter.replaceAllUsesWith(argAlloca, load); + rewriter.eraseOp(firstStore); + rewriter.eraseOp(argAlloca.getDefiningOp()); + + break; + } default: cir_cconv_unreachable("Unhandled ABIArgInfo::Kind"); } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp index 8ed553a8f7d2..f114dec0d058 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp @@ -99,6 +99,12 @@ FuncType LowerTypes::getFunctionType(const LowerFunctionInfo &FI) { } break; } + case ABIArgInfo::Indirect: { + mlir::Type argType = (FI.arg_begin() + ArgNo)->type; + ArgTypes[FirstIRArg] = + mlir::cir::PointerType::get(getMLIRContext(), argType); + break; + } default: cir_cconv_unreachable("Missing ABIArgInfo::Kind"); } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp index e28766985995..74de795ed622 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp @@ -188,7 +188,7 @@ AArch64ABIInfo::classifyArgumentType(Type Ty, bool IsVariadic, return ABIArgInfo::getDirect(argTy); } - cir_cconv_unreachable("NYI"); + return getNaturalAlignIndirect(Ty, /*ByVal=*/false); } std::unique_ptr From 97724175cd0996aeced7f0e66f4f916a54041394 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Wed, 6 Nov 2024 11:48:25 +0300 Subject: [PATCH 2/5] added test --- .../CIR/CallConvLowering/AArch64/aarch64-cc-structs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c index bc2f1d37d729..7847ad8b684b 100644 --- a/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c +++ b/clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c @@ -115,3 +115,14 @@ void pass_lt_128(LT_128 s) {} // LLVM: %[[#V1]] = alloca %struct.EQ_128, i64 1, align 4 // LLVM: store [2 x i64] %0, ptr %[[#V1]], align 8 void pass_eq_128(EQ_128 s) {} + +// CHECK: cir.func @pass_gt_128(%arg0: !cir.ptr +// CHECK: %[[#V0:]] = cir.alloca !cir.ptr, !cir.ptr>, [""] {alignment = 8 : i64} +// CHECK: cir.store %arg0, %[[#V0]] : !cir.ptr, !cir.ptr> +// CHECK: %[[#V1:]] = cir.load %[[#V0]] : !cir.ptr>, !cir.ptr + +// LLVM: void @pass_gt_128(ptr %0) +// LLVM: %[[#V1:]] = alloca ptr, i64 1, align 8 +// LLVM: store ptr %0, ptr %[[#V1]], align 8 +// LLVM: %[[#V2:]] = load ptr, ptr %[[#V1]], align 8 +void pass_gt_128(GT_128 s) {} From 7fb415a579959e8558c08e71056ae483d94ef685 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Wed, 6 Nov 2024 13:31:07 +0300 Subject: [PATCH 3/5] adds bunch of missed features --- clang/include/clang/CIR/MissingFeatures.h | 3 +++ .../CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 9b1eb419f3e0..412ac4385f4b 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -269,6 +269,9 @@ struct MissingFeatures { static bool ABIPointerParameterAttrs() { return false; } static bool ABITransparentUnionHandling() { return false; } static bool ABIPotentialArgAccess() { return false; } + static bool ABIByValAttribute() { return false; } + static bool ABIAlignmentAttribute() { return false; } + static bool ABINoAliasAttribute() { return false; } //-- Missing AST queries diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp index 26a032856c52..98133de4fb6c 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp @@ -226,8 +226,14 @@ void LowerModule::constructAttributeList(StringRef Name, // Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign())); cir_cconv_assert(!::cir::MissingFeatures::noFPClass()); break; - case ABIArgInfo::Indirect: + case ABIArgInfo::Indirect: { + cir_cconv_assert(!::cir::MissingFeatures::ABIInRegAttribute()); + cir_cconv_assert(!::cir::MissingFeatures::ABIByValAttribute()); + cir_cconv_assert(!::cir::MissingFeatures::ABINoAliasAttribute()); + cir_cconv_assert(!::cir::MissingFeatures::ABIAlignmentAttribute()); + cir_cconv_assert(!::cir::MissingFeatures::ABIPotentialArgAccess()); break; + } default: cir_cconv_unreachable("Missing ABIArgInfo::Kind"); } From e61116c4f04c302a40e1c7f2f82a7e831b895a8f Mon Sep 17 00:00:00 2001 From: gitoleg Date: Wed, 6 Nov 2024 16:55:21 +0300 Subject: [PATCH 4/5] refactoring --- clang/include/clang/CIR/ABIArgInfo.h | 10 ++++ .../TargetLowering/LowerFunction.cpp | 60 ++++++++++++------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/CIR/ABIArgInfo.h b/clang/include/clang/CIR/ABIArgInfo.h index 582feae157b2..818d3b62f13f 100644 --- a/clang/include/clang/CIR/ABIArgInfo.h +++ b/clang/include/clang/CIR/ABIArgInfo.h @@ -215,11 +215,21 @@ class ABIArgInfo { IndirectAttr.Align = align; } + bool getIndirectByVal() const { + assert(isIndirect() && "Invalid kind!"); + return IndirectByVal; + } + void setIndirectByVal(bool IBV) { assert(isIndirect() && "Invalid kind!"); IndirectByVal = IBV; } + bool getIndirectRealign() const { + assert((isIndirect() || isIndirectAliased()) && "Invalid kind!"); + return IndirectRealign; + } + void setIndirectRealign(bool IR) { assert((isIndirect() || isIndirectAliased()) && "Invalid kind!"); IndirectRealign = IR; diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index 691b1ebf28c1..4216ddf5a1d2 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -10,6 +10,7 @@ // are adapted to operate on the CIR dialect, however. // //===----------------------------------------------------------------------===// +#include #include "LowerFunction.h" #include "CIRToCIRArgMapping.h" #include "LowerCall.h" @@ -518,27 +519,44 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn, } case ABIArgInfo::Indirect: { auto AI = Fn.getArgument(FirstIRArg); - auto ptrTy = rewriter.getType(Arg.getType()); - ArgVals.push_back(AI); - - Value arg = SrcFn.getArgument(ArgNo); - cir_cconv_assert(arg.hasOneUse()); - auto *firstStore = *arg.user_begin(); - auto argAlloca = cast(firstStore).getAddr(); - - rewriter.setInsertionPoint(argAlloca.getDefiningOp()); - auto newAlloca = rewriter.create( - Fn.getLoc(), rewriter.getType(ptrTy), ptrTy, - /*name=*/StringRef(""), - /*alignment=*/rewriter.getI64IntegerAttr(8)); - - rewriter.create(newAlloca.getLoc(), AI, newAlloca.getResult()); - auto load = rewriter.create(newAlloca.getLoc(), newAlloca.getResult()); - - rewriter.replaceAllUsesWith(argAlloca, load); - rewriter.eraseOp(firstStore); - rewriter.eraseOp(argAlloca.getDefiningOp()); - + if (!hasScalarEvaluationKind(Ty)) { + // Aggregates and complex variables are accessed by reference. All we + // need to do is realign the value, if requested. Also, if the address + // may be aliased, copy it to ensure that the parameter variable is + // mutable and has a unique adress, as C requires. + if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { + cir_cconv_unreachable("NYI"); + } else { + // Inspired by EmitParamDecl, which is called in the end of + // EmitFunctionProlog in the original codegen + cir_cconv_assert(!ArgI.getIndirectByVal() && "For truly ABI indirect arguments"); + + auto ptrTy = rewriter.getType(Arg.getType()); + Value arg = SrcFn.getArgument(ArgNo); + cir_cconv_assert(arg.hasOneUse()); + auto *firstStore = *arg.user_begin(); + auto argAlloca = cast(firstStore).getAddr(); + + rewriter.setInsertionPoint(argAlloca.getDefiningOp()); + auto align = LM.getDataLayout().getABITypeAlign(ptrTy); + auto alignAttr = rewriter.getI64IntegerAttr(align.value()); + auto newAlloca = rewriter.create( + Fn.getLoc(), rewriter.getType(ptrTy), ptrTy, + /*name=*/StringRef(""), + /*alignment=*/alignAttr); + + rewriter.create(newAlloca.getLoc(), AI, newAlloca.getResult()); + auto load = rewriter.create(newAlloca.getLoc(), newAlloca.getResult()); + + rewriter.replaceAllUsesWith(argAlloca, load); + rewriter.eraseOp(firstStore); + rewriter.eraseOp(argAlloca.getDefiningOp()); + + ArgVals.push_back(AI); + } + } else { + cir_cconv_unreachable("NYI"); + } break; } default: From 89a27fe064516251cc17f685d951ea45f301cec8 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Wed, 6 Nov 2024 17:18:30 +0300 Subject: [PATCH 5/5] clang-format ... --- .../Transforms/TargetLowering/LowerCall.cpp | 2 +- .../Transforms/TargetLowering/LowerFunction.cpp | 14 ++++++++------ .../Transforms/TargetLowering/LowerTypes.cpp | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp index 98133de4fb6c..23c6c85a9723 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerCall.cpp @@ -233,7 +233,7 @@ void LowerModule::constructAttributeList(StringRef Name, cir_cconv_assert(!::cir::MissingFeatures::ABIAlignmentAttribute()); cir_cconv_assert(!::cir::MissingFeatures::ABIPotentialArgAccess()); break; - } + } default: cir_cconv_unreachable("Missing ABIArgInfo::Kind"); } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index 4216ddf5a1d2..67e5a012cb6e 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -10,7 +10,6 @@ // are adapted to operate on the CIR dialect, however. // //===----------------------------------------------------------------------===// -#include #include "LowerFunction.h" #include "CIRToCIRArgMapping.h" #include "LowerCall.h" @@ -529,15 +528,16 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn, } else { // Inspired by EmitParamDecl, which is called in the end of // EmitFunctionProlog in the original codegen - cir_cconv_assert(!ArgI.getIndirectByVal() && "For truly ABI indirect arguments"); - + cir_cconv_assert(!ArgI.getIndirectByVal() && + "For truly ABI indirect arguments"); + auto ptrTy = rewriter.getType(Arg.getType()); Value arg = SrcFn.getArgument(ArgNo); cir_cconv_assert(arg.hasOneUse()); auto *firstStore = *arg.user_begin(); auto argAlloca = cast(firstStore).getAddr(); - rewriter.setInsertionPoint(argAlloca.getDefiningOp()); + rewriter.setInsertionPoint(argAlloca.getDefiningOp()); auto align = LM.getDataLayout().getABITypeAlign(ptrTy); auto alignAttr = rewriter.getI64IntegerAttr(align.value()); auto newAlloca = rewriter.create( @@ -545,8 +545,10 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn, /*name=*/StringRef(""), /*alignment=*/alignAttr); - rewriter.create(newAlloca.getLoc(), AI, newAlloca.getResult()); - auto load = rewriter.create(newAlloca.getLoc(), newAlloca.getResult()); + rewriter.create(newAlloca.getLoc(), AI, + newAlloca.getResult()); + auto load = rewriter.create(newAlloca.getLoc(), + newAlloca.getResult()); rewriter.replaceAllUsesWith(argAlloca, load); rewriter.eraseOp(firstStore); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp index f114dec0d058..5a3382dc40e6 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp @@ -100,9 +100,9 @@ FuncType LowerTypes::getFunctionType(const LowerFunctionInfo &FI) { break; } case ABIArgInfo::Indirect: { - mlir::Type argType = (FI.arg_begin() + ArgNo)->type; + mlir::Type argType = (FI.arg_begin() + ArgNo)->type; ArgTypes[FirstIRArg] = - mlir::cir::PointerType::get(getMLIRContext(), argType); + mlir::cir::PointerType::get(getMLIRContext(), argType); break; } default: