Skip to content

Commit d472146

Browse files
authored
[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 18ad5b8 commit d472146

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
@@ -3208,6 +3208,7 @@ class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []> :
32083208
dag commonArgs = (ins
32093209
OptionalAttr<FlatSymbolRefAttr>:$callee,
32103210
Variadic<CIR_AnyType>:$arg_ops,
3211+
DefaultValuedAttr<CallingConv, "CallingConv::C">:$calling_conv,
32113212
ExtraFuncAttr:$extra_attrs,
32123213
OptionalAttr<ASTCallExprInterface>:$ast
32133214
);
@@ -3251,10 +3252,13 @@ def CallOp : CIR_CallOp<"call"> {
32513252
let builders = [
32523253
OpBuilder<(ins "SymbolRefAttr":$callee, "mlir::Type":$resType,
32533254
CArg<"ValueRange", "{}">:$operands,
3255+
CArg<"CallingConv", "CallingConv::C">:$callingConv,
32543256
CArg<"UnitAttr", "{}">:$exception), [{
32553257
$_state.addOperands(operands);
32563258
if (callee)
32573259
$_state.addAttribute("callee", callee);
3260+
$_state.addAttribute("calling_conv",
3261+
CallingConvAttr::get($_builder.getContext(), callingConv));
32583262
if (exception)
32593263
$_state.addAttribute("exception", exception);
32603264
if (resType && !isa<VoidType>(resType))
@@ -3263,11 +3267,14 @@ def CallOp : CIR_CallOp<"call"> {
32633267
OpBuilder<(ins "Value":$ind_target,
32643268
"FuncType":$fn_type,
32653269
CArg<"ValueRange", "{}">:$operands,
3270+
CArg<"CallingConv", "CallingConv::C">:$callingConv,
32663271
CArg<"UnitAttr", "{}">:$exception), [{
32673272
$_state.addOperands(ValueRange{ind_target});
32683273
$_state.addOperands(operands);
32693274
if (!fn_type.isVoid())
32703275
$_state.addTypes(fn_type.getReturnType());
3276+
$_state.addAttribute("calling_conv",
3277+
CallingConvAttr::get($_builder.getContext(), callingConv));
32713278
if (exception)
32723279
$_state.addAttribute("exception", exception);
32733280
}]>
@@ -3307,13 +3314,17 @@ def TryCallOp : CIR_CallOp<"try_call",
33073314
"Block *":$cont, "Block *":$landing_pad,
33083315
CArg<"ValueRange", "{}">:$operands,
33093316
CArg<"ValueRange", "{}">:$contOperands,
3310-
CArg<"ValueRange", "{}">:$landingPadOperands), [{
3317+
CArg<"ValueRange", "{}">:$landingPadOperands,
3318+
CArg<"CallingConv", "CallingConv::C">:$callingConv), [{
33113319
$_state.addOperands(operands);
33123320
if (callee)
33133321
$_state.addAttribute("callee", callee);
33143322
if (resType && !isa<VoidType>(resType))
33153323
$_state.addTypes(resType);
33163324

3325+
$_state.addAttribute("calling_conv",
3326+
CallingConvAttr::get($_builder.getContext(), callingConv));
3327+
33173328
// Handle branches
33183329
$_state.addOperands(contOperands);
33193330
$_state.addOperands(landingPadOperands);
@@ -3332,14 +3343,18 @@ def TryCallOp : CIR_CallOp<"try_call",
33323343
"Block *":$cont, "Block *":$landing_pad,
33333344
CArg<"ValueRange", "{}">:$operands,
33343345
CArg<"ValueRange", "{}">:$contOperands,
3335-
CArg<"ValueRange", "{}">:$landingPadOperands), [{
3346+
CArg<"ValueRange", "{}">:$landingPadOperands,
3347+
CArg<"CallingConv", "CallingConv::C">:$callingConv), [{
33363348
::llvm::SmallVector<mlir::Value, 4> finalCallOperands({ind_target});
33373349
finalCallOperands.append(operands.begin(), operands.end());
33383350
$_state.addOperands(finalCallOperands);
33393351

33403352
if (!fn_type.isVoid())
33413353
$_state.addTypes(fn_type.getReturnType());
33423354

3355+
$_state.addAttribute("calling_conv",
3356+
CallingConvAttr::get($_builder.getContext(), callingConv));
3357+
33433358
// Handle branches
33443359
$_state.addOperands(contOperands);
33453360
$_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
@@ -2874,13 +2874,26 @@ static ::mlir::ParseResult parseCallCommon(::mlir::OpAsmParser &parser,
28742874
return ::mlir::failure();
28752875
}
28762876

2877+
if (parser.parseOptionalKeyword("cc").succeeded()) {
2878+
if (parser.parseLParen().failed())
2879+
return failure();
2880+
mlir::cir::CallingConv callingConv;
2881+
if (parseCIRKeyword<mlir::cir::CallingConv>(parser, callingConv).failed())
2882+
return failure();
2883+
if (parser.parseRParen().failed())
2884+
return failure();
2885+
result.addAttribute("calling_conv", mlir::cir::CallingConvAttr::get(
2886+
builder.getContext(), callingConv));
2887+
}
2888+
28772889
return ::mlir::success();
28782890
}
28792891

28802892
void printCallCommon(Operation *op, mlir::Value indirectCallee,
28812893
mlir::FlatSymbolRefAttr flatSym,
28822894
::mlir::OpAsmPrinter &state,
28832895
::mlir::cir::ExtraFuncAttributesAttr extraAttrs,
2896+
::mlir::cir::CallingConv callingConv,
28842897
::mlir::UnitAttr exception = {},
28852898
mlir::Block *cont = nullptr,
28862899
mlir::Block *landingPad = nullptr) {
@@ -2932,13 +2945,21 @@ void printCallCommon(Operation *op, mlir::Value indirectCallee,
29322945
elidedAttrs.push_back("callee");
29332946
elidedAttrs.push_back("ast");
29342947
elidedAttrs.push_back("extra_attrs");
2948+
elidedAttrs.push_back("calling_conv");
29352949
elidedAttrs.push_back("exception");
29362950
elidedAttrs.push_back("operandSegmentSizes");
29372951

29382952
state.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
29392953
state << ' ' << ":";
29402954
state << ' ';
29412955
state.printFunctionalType(op->getOperands().getTypes(), op->getResultTypes());
2956+
2957+
if (callingConv != mlir::cir::CallingConv::C) {
2958+
state << " cc(";
2959+
state << stringifyCallingConv(callingConv);
2960+
state << ")";
2961+
}
2962+
29422963
if (!extraAttrs.getElements().empty()) {
29432964
state << " extra(";
29442965
state.printAttributeWithoutType(extraAttrs);
@@ -2959,9 +2980,10 @@ ::mlir::ParseResult CallOp::parse(::mlir::OpAsmParser &parser,
29592980

29602981
void CallOp::print(::mlir::OpAsmPrinter &state) {
29612982
mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr;
2983+
mlir::cir::CallingConv callingConv = getCallingConv();
29622984
mlir::UnitAttr exception = getExceptionAttr();
29632985
printCallCommon(*this, indirectCallee, getCalleeAttr(), state,
2964-
getExtraAttrs(), exception);
2986+
getExtraAttrs(), callingConv, exception);
29652987
}
29662988

29672989
//===----------------------------------------------------------------------===//
@@ -3010,8 +3032,9 @@ ::mlir::ParseResult TryCallOp::parse(::mlir::OpAsmParser &parser,
30103032

30113033
void TryCallOp::print(::mlir::OpAsmPrinter &state) {
30123034
mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr;
3035+
mlir::cir::CallingConv callingConv = getCallingConv();
30133036
printCallCommon(*this, indirectCallee, getCalleeAttr(), state,
3014-
getExtraAttrs(), {}, getCont(), getLandingPad());
3037+
getExtraAttrs(), callingConv, {}, getCont(), getLandingPad());
30153038
}
30163039

30173040
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)