Skip to content

Commit e0d85c1

Browse files
seven-milelanza
authored andcommitted
[CIR][Dialect] Add calling convention attribute to cir.call op (#828)
The first patch to fix #803 . This PR adds the calling convention attribute to CallOp directly, which is similar to LLVM, rather than adding the information to function type, which mimics Clang AST function type. The syntax of it in CIR assembly is between the function type and extra attributes, as follows: ```mlir %1 = cir.call %fnptr(%a) : (!fnptr, !s32i) -> !s32i cc(spir_kernel) extra(#fn_attr) ``` The verification of direct calls is not included. It will be included in the next patch extending CIRGen & Lowering. --- For every builder method of Call Op, an optional parameter `callingConv` is inserted right before the parameter of extra attribute. However, apart from the parser / printer, this PR does not introduce any functional changes.
1 parent ba7a28b commit e0d85c1

File tree

6 files changed

+110
-36
lines changed

6 files changed

+110
-36
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -622,10 +622,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
622622
mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(),
623623
mlir::Type returnType = mlir::cir::VoidType(),
624624
mlir::ValueRange operands = mlir::ValueRange(),
625+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C,
625626
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
626627

627-
mlir::cir::CallOp callOp =
628-
create<mlir::cir::CallOp>(loc, callee, returnType, operands);
628+
mlir::cir::CallOp callOp = create<mlir::cir::CallOp>(
629+
loc, callee, returnType, operands, callingConv);
629630

630631
if (extraFnAttr) {
631632
callOp->setAttr("extra_attrs", extraFnAttr);
@@ -641,41 +642,44 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
641642
mlir::cir::CallOp
642643
createCallOp(mlir::Location loc, mlir::cir::FuncOp callee,
643644
mlir::ValueRange operands = mlir::ValueRange(),
645+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C,
644646
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
645647
return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
646648
callee.getFunctionType().getReturnType(), operands,
647-
extraFnAttr);
649+
callingConv, extraFnAttr);
648650
}
649651

650-
mlir::cir::CallOp
651-
createIndirectCallOp(mlir::Location loc, mlir::Value ind_target,
652-
mlir::cir::FuncType fn_type,
653-
mlir::ValueRange operands = mlir::ValueRange(),
654-
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
652+
mlir::cir::CallOp createIndirectCallOp(
653+
mlir::Location loc, mlir::Value ind_target, mlir::cir::FuncType fn_type,
654+
mlir::ValueRange operands = mlir::ValueRange(),
655+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C,
656+
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
655657

656658
llvm::SmallVector<mlir::Value, 4> resOperands({ind_target});
657659
resOperands.append(operands.begin(), operands.end());
658660

659661
return createCallOp(loc, mlir::SymbolRefAttr(), fn_type.getReturnType(),
660-
resOperands, extraFnAttr);
662+
resOperands, callingConv, extraFnAttr);
661663
}
662664

663665
mlir::cir::CallOp
664666
createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
665667
mlir::ValueRange operands = mlir::ValueRange(),
668+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C,
666669
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
667670
return createCallOp(loc, callee, mlir::cir::VoidType(), operands,
668-
extraFnAttr);
669-
}
670-
671-
mlir::cir::CallOp
672-
createTryCallOp(mlir::Location loc,
673-
mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(),
674-
mlir::Type returnType = mlir::cir::VoidType(),
675-
mlir::ValueRange operands = mlir::ValueRange(),
676-
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
677-
mlir::cir::CallOp tryCallOp = create<mlir::cir::CallOp>(
678-
loc, callee, returnType, operands, getUnitAttr());
671+
callingConv, extraFnAttr);
672+
}
673+
674+
mlir::cir::CallOp createTryCallOp(
675+
mlir::Location loc, mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(),
676+
mlir::Type returnType = mlir::cir::VoidType(),
677+
mlir::ValueRange operands = mlir::ValueRange(),
678+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C,
679+
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
680+
mlir::cir::CallOp tryCallOp =
681+
create<mlir::cir::CallOp>(loc, callee, returnType, operands,
682+
callingConv, /*exception=*/getUnitAttr());
679683
if (extraFnAttr) {
680684
tryCallOp->setAttr("extra_attrs", extraFnAttr);
681685
} else {
@@ -687,23 +691,23 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
687691
return tryCallOp;
688692
}
689693

690-
mlir::cir::CallOp
691-
createTryCallOp(mlir::Location loc, mlir::cir::FuncOp callee,
692-
mlir::ValueRange operands,
693-
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
694+
mlir::cir::CallOp createTryCallOp(
695+
mlir::Location loc, mlir::cir::FuncOp callee, mlir::ValueRange operands,
696+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C,
697+
mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) {
694698
return createTryCallOp(loc, mlir::SymbolRefAttr::get(callee),
695699
callee.getFunctionType().getReturnType(), operands,
696-
extraFnAttr);
700+
callingConv, extraFnAttr);
697701
}
698702

699-
mlir::cir::CallOp createIndirectTryCallOp(mlir::Location loc,
700-
mlir::Value ind_target,
701-
mlir::cir::FuncType fn_type,
702-
mlir::ValueRange operands) {
703+
mlir::cir::CallOp createIndirectTryCallOp(
704+
mlir::Location loc, mlir::Value ind_target, mlir::cir::FuncType fn_type,
705+
mlir::ValueRange operands,
706+
mlir::cir::CallingConv callingConv = mlir::cir::CallingConv::C) {
703707
llvm::SmallVector<mlir::Value, 4> resOperands({ind_target});
704708
resOperands.append(operands.begin(), operands.end());
705709
return createTryCallOp(loc, mlir::SymbolRefAttr(), fn_type.getReturnType(),
706-
resOperands);
710+
resOperands, callingConv);
707711
}
708712

709713
struct GetMethodResults {

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3217,6 +3217,7 @@ class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []> :
32173217
dag commonArgs = (ins
32183218
OptionalAttr<FlatSymbolRefAttr>:$callee,
32193219
Variadic<CIR_AnyType>:$arg_ops,
3220+
DefaultValuedAttr<CallingConv, "CallingConv::C">:$calling_conv,
32203221
ExtraFuncAttr:$extra_attrs,
32213222
OptionalAttr<ASTCallExprInterface>:$ast
32223223
);
@@ -3260,10 +3261,13 @@ def CallOp : CIR_CallOp<"call"> {
32603261
let builders = [
32613262
OpBuilder<(ins "SymbolRefAttr":$callee, "mlir::Type":$resType,
32623263
CArg<"ValueRange", "{}">:$operands,
3264+
CArg<"CallingConv", "CallingConv::C">:$callingConv,
32633265
CArg<"UnitAttr", "{}">:$exception), [{
32643266
$_state.addOperands(operands);
32653267
if (callee)
32663268
$_state.addAttribute("callee", callee);
3269+
$_state.addAttribute("calling_conv",
3270+
CallingConvAttr::get($_builder.getContext(), callingConv));
32673271
if (exception)
32683272
$_state.addAttribute("exception", exception);
32693273
if (resType && !isa<VoidType>(resType))
@@ -3272,11 +3276,14 @@ def CallOp : CIR_CallOp<"call"> {
32723276
OpBuilder<(ins "Value":$ind_target,
32733277
"FuncType":$fn_type,
32743278
CArg<"ValueRange", "{}">:$operands,
3279+
CArg<"CallingConv", "CallingConv::C">:$callingConv,
32753280
CArg<"UnitAttr", "{}">:$exception), [{
32763281
$_state.addOperands(ValueRange{ind_target});
32773282
$_state.addOperands(operands);
32783283
if (!fn_type.isVoid())
32793284
$_state.addTypes(fn_type.getReturnType());
3285+
$_state.addAttribute("calling_conv",
3286+
CallingConvAttr::get($_builder.getContext(), callingConv));
32803287
if (exception)
32813288
$_state.addAttribute("exception", exception);
32823289
}]>
@@ -3316,13 +3323,17 @@ def TryCallOp : CIR_CallOp<"try_call",
33163323
"Block *":$cont, "Block *":$landing_pad,
33173324
CArg<"ValueRange", "{}">:$operands,
33183325
CArg<"ValueRange", "{}">:$contOperands,
3319-
CArg<"ValueRange", "{}">:$landingPadOperands), [{
3326+
CArg<"ValueRange", "{}">:$landingPadOperands,
3327+
CArg<"CallingConv", "CallingConv::C">:$callingConv), [{
33203328
$_state.addOperands(operands);
33213329
if (callee)
33223330
$_state.addAttribute("callee", callee);
33233331
if (resType && !isa<VoidType>(resType))
33243332
$_state.addTypes(resType);
33253333

3334+
$_state.addAttribute("calling_conv",
3335+
CallingConvAttr::get($_builder.getContext(), callingConv));
3336+
33263337
// Handle branches
33273338
$_state.addOperands(contOperands);
33283339
$_state.addOperands(landingPadOperands);
@@ -3341,14 +3352,18 @@ def TryCallOp : CIR_CallOp<"try_call",
33413352
"Block *":$cont, "Block *":$landing_pad,
33423353
CArg<"ValueRange", "{}">:$operands,
33433354
CArg<"ValueRange", "{}">:$contOperands,
3344-
CArg<"ValueRange", "{}">:$landingPadOperands), [{
3355+
CArg<"ValueRange", "{}">:$landingPadOperands,
3356+
CArg<"CallingConv", "CallingConv::C">:$callingConv), [{
33453357
::llvm::SmallVector<mlir::Value, 4> finalCallOperands({ind_target});
33463358
finalCallOperands.append(operands.begin(), operands.end());
33473359
$_state.addOperands(finalCallOperands);
33483360

33493361
if (!fn_type.isVoid())
33503362
$_state.addTypes(fn_type.getReturnType());
33513363

3364+
$_state.addAttribute("calling_conv",
3365+
CallingConvAttr::get($_builder.getContext(), callingConv));
3366+
33523367
// Handle branches
33533368
$_state.addOperands(contOperands);
33543369
$_state.addOperands(landingPadOperands);

clang/include/clang/CIR/Interfaces/CIROpInterfaces.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ let cppNamespace = "::mlir::cir" in {
3434
"Return the number of operands, accounts for indirect call or "
3535
"exception info",
3636
"unsigned", "getNumArgOperands", (ins)>,
37+
InterfaceMethod<
38+
"Return the calling convention of the call operation",
39+
"mlir::cir::CallingConv", "getCallingConv", (ins)>,
3740
];
3841
}
3942

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,10 @@ buildCallLikeOp(CIRGenFunction &CGF, mlir::Location callLoc,
487487
assert(builder.getInsertionBlock() && "expected valid basic block");
488488
if (indirectFuncTy)
489489
return builder.createIndirectCallOp(
490-
callLoc, indirectFuncVal, indirectFuncTy, CIRCallArgs, extraFnAttrs);
491-
return builder.createCallOp(callLoc, directFuncOp, CIRCallArgs, extraFnAttrs);
490+
callLoc, indirectFuncVal, indirectFuncTy, CIRCallArgs,
491+
mlir::cir::CallingConv::C, extraFnAttrs);
492+
return builder.createCallOp(callLoc, directFuncOp, CIRCallArgs,
493+
mlir::cir::CallingConv::C, extraFnAttrs);
492494
}
493495

494496
RValue CIRGenFunction::buildCall(const CIRGenFunctionInfo &CallInfo,

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2881,13 +2881,26 @@ static ::mlir::ParseResult parseCallCommon(::mlir::OpAsmParser &parser,
28812881
return ::mlir::failure();
28822882
}
28832883

2884+
if (parser.parseOptionalKeyword("cc").succeeded()) {
2885+
if (parser.parseLParen().failed())
2886+
return failure();
2887+
mlir::cir::CallingConv callingConv;
2888+
if (parseCIRKeyword<mlir::cir::CallingConv>(parser, callingConv).failed())
2889+
return failure();
2890+
if (parser.parseRParen().failed())
2891+
return failure();
2892+
result.addAttribute("calling_conv", mlir::cir::CallingConvAttr::get(
2893+
builder.getContext(), callingConv));
2894+
}
2895+
28842896
return ::mlir::success();
28852897
}
28862898

28872899
void printCallCommon(Operation *op, mlir::Value indirectCallee,
28882900
mlir::FlatSymbolRefAttr flatSym,
28892901
::mlir::OpAsmPrinter &state,
28902902
::mlir::cir::ExtraFuncAttributesAttr extraAttrs,
2903+
::mlir::cir::CallingConv callingConv,
28912904
::mlir::UnitAttr exception = {},
28922905
mlir::Block *cont = nullptr,
28932906
mlir::Block *landingPad = nullptr) {
@@ -2939,13 +2952,21 @@ void printCallCommon(Operation *op, mlir::Value indirectCallee,
29392952
elidedAttrs.push_back("callee");
29402953
elidedAttrs.push_back("ast");
29412954
elidedAttrs.push_back("extra_attrs");
2955+
elidedAttrs.push_back("calling_conv");
29422956
elidedAttrs.push_back("exception");
29432957
elidedAttrs.push_back("operandSegmentSizes");
29442958

29452959
state.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
29462960
state << ' ' << ":";
29472961
state << ' ';
29482962
state.printFunctionalType(op->getOperands().getTypes(), op->getResultTypes());
2963+
2964+
if (callingConv != mlir::cir::CallingConv::C) {
2965+
state << " cc(";
2966+
state << stringifyCallingConv(callingConv);
2967+
state << ")";
2968+
}
2969+
29492970
if (!extraAttrs.getElements().empty()) {
29502971
state << " extra(";
29512972
state.printAttributeWithoutType(extraAttrs);
@@ -2966,9 +2987,10 @@ ::mlir::ParseResult CallOp::parse(::mlir::OpAsmParser &parser,
29662987

29672988
void CallOp::print(::mlir::OpAsmPrinter &state) {
29682989
mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr;
2990+
mlir::cir::CallingConv callingConv = getCallingConv();
29692991
mlir::UnitAttr exception = getExceptionAttr();
29702992
printCallCommon(*this, indirectCallee, getCalleeAttr(), state,
2971-
getExtraAttrs(), exception);
2993+
getExtraAttrs(), callingConv, exception);
29722994
}
29732995

29742996
//===----------------------------------------------------------------------===//
@@ -3024,8 +3046,9 @@ ::mlir::ParseResult TryCallOp::parse(::mlir::OpAsmParser &parser,
30243046

30253047
void TryCallOp::print(::mlir::OpAsmPrinter &state) {
30263048
mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr;
3049+
mlir::cir::CallingConv callingConv = getCallingConv();
30273050
printCallCommon(*this, indirectCallee, getCalleeAttr(), state,
3028-
getExtraAttrs(), {}, getCont(), getLandingPad());
3051+
getExtraAttrs(), callingConv, {}, getCont(), getLandingPad());
30293052
}
30303053

30313054
mlir::SuccessorOperands TryCallOp::getSuccessorOperands(unsigned index) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: cir-opt %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
4+
!s32i = !cir.int<s, 32>
5+
!fnptr = !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>
6+
7+
module {
8+
cir.func @my_add(%a: !s32i, %b: !s32i) -> !s32i cc(spir_function) {
9+
%c = cir.binop(add, %a, %b) : !s32i
10+
cir.return %c : !s32i
11+
}
12+
13+
cir.func @ind(%fnptr: !fnptr, %a : !s32i) {
14+
%1 = cir.call %fnptr(%a) : (!fnptr, !s32i) -> !s32i cc(spir_kernel)
15+
%2 = cir.call %fnptr(%a) : (!fnptr, !s32i) -> !s32i cc(spir_function)
16+
17+
%3 = cir.try_call @my_add(%1, %2) ^continue, ^landing_pad : (!s32i, !s32i) -> !s32i cc(spir_function)
18+
^continue:
19+
cir.br ^landing_pad
20+
^landing_pad:
21+
cir.return
22+
}
23+
}
24+
25+
// CHECK: %{{[0-9]+}} = cir.call %arg0(%arg1) : (!cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !s32i) -> !s32i cc(spir_kernel)
26+
// CHECK: %{{[0-9]+}} = cir.call %arg0(%arg1) : (!cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !s32i) -> !s32i cc(spir_function)
27+
// CHECK: %{{[0-9]+}} = cir.try_call @my_add(%{{[0-9]+}}, %{{[0-9]+}}) ^{{.+}}, ^{{.+}} : (!s32i, !s32i) -> !s32i cc(spir_function)

0 commit comments

Comments
 (0)