Skip to content

[CIR][ABI][AArch64][Lowering] support for passing struct types > 128 bits #1068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions clang/include/clang/CIR/ABIArgInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,14 @@ void LowerModule::constructAttributeList(StringRef Name,
// Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign()));
cir_cconv_assert(!::cir::MissingFeatures::noFPClass());
break;
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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,51 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn,
rewriter.eraseOp(argAlloca.getDefiningOp());
break;
}
case ABIArgInfo::Indirect: {
auto AI = Fn.getArgument(FirstIRArg);
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<PointerType>(Arg.getType());
Value arg = SrcFn.getArgument(ArgNo);
cir_cconv_assert(arg.hasOneUse());
auto *firstStore = *arg.user_begin();
auto argAlloca = cast<StoreOp>(firstStore).getAddr();

rewriter.setInsertionPoint(argAlloca.getDefiningOp());
auto align = LM.getDataLayout().getABITypeAlign(ptrTy);
auto alignAttr = rewriter.getI64IntegerAttr(align.value());
auto newAlloca = rewriter.create<AllocaOp>(
Fn.getLoc(), rewriter.getType<PointerType>(ptrTy), ptrTy,
/*name=*/StringRef(""),
/*alignment=*/alignAttr);

rewriter.create<StoreOp>(newAlloca.getLoc(), AI,
newAlloca.getResult());
auto load = rewriter.create<LoadOp>(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:
cir_cconv_unreachable("Unhandled ABIArgInfo::Kind");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TargetLoweringInfo>
Expand Down
11 changes: 11 additions & 0 deletions clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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<!ty_GT_128_>
// CHECK: %[[#V0:]] = cir.alloca !cir.ptr<!ty_GT_128_>, !cir.ptr<!cir.ptr<!ty_GT_128_>>, [""] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %[[#V0]] : !cir.ptr<!ty_GT_128_>, !cir.ptr<!cir.ptr<!ty_GT_128_>>
// CHECK: %[[#V1:]] = cir.load %[[#V0]] : !cir.ptr<!cir.ptr<!ty_GT_128_>>, !cir.ptr<!ty_GT_128_>

// 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) {}