@@ -19,8 +19,8 @@ include "clang/CIR/Dialect/IR/CIRTypes.td"
19
19
include "clang/CIR/Dialect/IR/CIRAttrs.td"
20
20
21
21
include "clang/CIR/Interfaces/ASTAttrInterfaces.td"
22
+ include "clang/CIR/Interfaces/CIROpInterfaces.td"
22
23
23
- include "mlir/Interfaces/CallInterfaces.td"
24
24
include "mlir/Interfaces/ControlFlowInterfaces.td"
25
25
include "mlir/Interfaces/FunctionInterfaces.td"
26
26
include "mlir/Interfaces/InferTypeOpInterface.td"
@@ -1672,14 +1672,39 @@ def GetMemberOp : CIR_Op<"get_member"> {
1672
1672
let hasVerifier = 1;
1673
1673
}
1674
1674
1675
+ //===----------------------------------------------------------------------===//
1676
+ // VecInsertOp
1677
+ //===----------------------------------------------------------------------===//
1678
+
1679
+ def VecInsertOp : CIR_Op<"vec.insert", [Pure,
1680
+ TypesMatchWith<"argument type matches vector element type", "vec", "value",
1681
+ "$_self.cast<VectorType>().getEltType()">,
1682
+ AllTypesMatch<["result", "vec"]>]> {
1683
+
1684
+ let summary = "Insert one element into a vector object";
1685
+ let description = [{
1686
+ The `cir.vec.insert` operation replaces the element of the given vector at
1687
+ the given index with the given value. The new vector with the inserted
1688
+ element is returned.
1689
+ }];
1690
+
1691
+ let arguments = (ins CIR_VectorType:$vec, AnyType:$value, CIR_IntType:$index);
1692
+ let results = (outs CIR_VectorType:$result);
1693
+
1694
+ let assemblyFormat = [{
1695
+ $value `,` $vec `[` $index `:` type($index) `]` attr-dict `:` type($vec)
1696
+ }];
1697
+
1698
+ let hasVerifier = 0;
1699
+ }
1700
+
1675
1701
//===----------------------------------------------------------------------===//
1676
1702
// VecExtractOp
1677
1703
//===----------------------------------------------------------------------===//
1678
1704
1679
1705
def VecExtractOp : CIR_Op<"vec.extract", [Pure,
1680
- TypesMatchWith<"type of 'result' matches element type of 'vec'",
1681
- "vec", "result",
1682
- "$_self.cast<VectorType>().getEltType()">]> {
1706
+ TypesMatchWith<"type of 'result' matches element type of 'vec'", "vec",
1707
+ "result", "$_self.cast<VectorType>().getEltType()">]> {
1683
1708
1684
1709
let summary = "Extract one element from a vector object";
1685
1710
let description = [{
@@ -1691,7 +1716,7 @@ def VecExtractOp : CIR_Op<"vec.extract", [Pure,
1691
1716
let results = (outs CIR_AnyType:$result);
1692
1717
1693
1718
let assemblyFormat = [{
1694
- $vec `[` $index `:` type($index) `]` type($vec) `-> ` type($result) attr-dict
1719
+ $vec `[` $index `:` type($index) `]` attr-dict `: ` type($vec)
1695
1720
}];
1696
1721
1697
1722
let hasVerifier = 0;
@@ -1909,12 +1934,43 @@ def FuncOp : CIR_Op<"func", [
1909
1934
}
1910
1935
1911
1936
//===----------------------------------------------------------------------===//
1912
- // CallOp
1937
+ // CallOp and TryCallOp
1913
1938
//===----------------------------------------------------------------------===//
1914
1939
1915
- def CallOp : CIR_Op<"call",
1916
- [DeclareOpInterfaceMethods<CallOpInterface>,
1917
- DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
1940
+ class CIR_CallOp<string mnemonic> :
1941
+ Op<CIR_Dialect, mnemonic,
1942
+ [DeclareOpInterfaceMethods<CIRCallOpInterface>,
1943
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
1944
+ let extraClassDeclaration = [{
1945
+ /// Get the argument operands to the called function.
1946
+ OperandRange getArgOperands() {
1947
+ return {arg_operand_begin(), arg_operand_end()};
1948
+ }
1949
+
1950
+ MutableOperandRange getArgOperandsMutable() {
1951
+ llvm_unreachable("NYI");
1952
+ }
1953
+
1954
+ /// Return the callee of this operation
1955
+ CallInterfaceCallable getCallableForCallee() {
1956
+ return (*this)->getAttrOfType<SymbolRefAttr>("callee");
1957
+ }
1958
+
1959
+ /// Set the callee for this operation.
1960
+ void setCalleeFromCallable(::mlir::CallInterfaceCallable callee) {
1961
+ if (auto calling =
1962
+ (*this)->getAttrOfType<mlir::SymbolRefAttr>(getCalleeAttrName()))
1963
+ (*this)->setAttr(getCalleeAttrName(), callee.get<mlir::SymbolRefAttr>());
1964
+ setOperand(0, callee.get<mlir::Value>());
1965
+ }
1966
+ }];
1967
+
1968
+ let hasCustomAssemblyFormat = 1;
1969
+ let skipDefaultBuilders = 1;
1970
+ let hasVerifier = 0;
1971
+ }
1972
+
1973
+ def CallOp : CIR_CallOp<"call"> {
1918
1974
let summary = "call operation";
1919
1975
let description = [{
1920
1976
The `call` operation represents a direct call to a function that is within
@@ -1966,39 +2022,56 @@ def CallOp : CIR_Op<"call",
1966
2022
$_state.addAttribute("callee", callee);
1967
2023
$_state.addTypes(resType);
1968
2024
}]>];
2025
+ }
1969
2026
1970
- let extraClassDeclaration = [{
1971
- mlir::Value getIndirectCallee() {
1972
- assert(!getCallee() && "only works for indirect call");
1973
- return *arg_operand_begin();
1974
- }
2027
+ def TryCallOp : CIR_CallOp<"try_call"> {
2028
+ let summary = "try call operation";
2029
+ let description = [{
2030
+ Works very similar to `cir.call` but passes down an exception object
2031
+ in case anything is thrown by the callee. Upon the callee throwing,
2032
+ `cir.try_call` goes to current `cir.scope`'s `abort` label, otherwise
2033
+ execution follows to the `continue` label.
1975
2034
1976
- operand_iterator arg_operand_begin() {
1977
- auto arg_begin = operand_begin();
1978
- if (!getCallee())
1979
- arg_begin++;
1980
- return arg_begin;
1981
- }
1982
- operand_iterator arg_operand_end() { return operand_end(); }
2035
+ To walk the operands for this operation, use `getNumArgOperands()`,
2036
+ `getArgOperand()`, `getArgOperands()`, `arg_operand_begin()` and
2037
+ `arg_operand_begin()`. Avoid using `getNumOperands()`, `getOperand()`,
2038
+ `operand_begin()`, etc, direclty - might be misleading given the
2039
+ exception object address is also part of the raw operation's operands.
2040
+ ``
1983
2041
1984
- /// Return the operand at index 'i', accounts for indirect call.
1985
- Value getArgOperand(unsigned i) {
1986
- if (!getCallee())
1987
- i++;
1988
- return getOperand(i);
1989
- }
2042
+ Example:
1990
2043
1991
- /// Return the number of operands, , accounts for indirect call.
1992
- unsigned getNumArgOperands() {
1993
- if (!getCallee())
1994
- return this->getOperation()->getNumOperands()-1;
1995
- return this->getOperation()->getNumOperands();
1996
- }
2044
+ ```mlir
2045
+ %r = cir.try_call @division(%1, %2), ^continue_A, ^abort, %0
2046
+ ```
1997
2047
}];
1998
2048
1999
- let hasCustomAssemblyFormat = 1;
2000
- let skipDefaultBuilders = 1;
2001
- let hasVerifier = 0;
2049
+ let arguments = (ins OptionalAttr<FlatSymbolRefAttr>:$callee,
2050
+ Variadic<CIR_AnyType>:$operands,
2051
+ OptionalAttr<ASTCallExprInterface>:$ast);
2052
+ let results = (outs Variadic<CIR_AnyType>);
2053
+
2054
+ let builders = [
2055
+ OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{
2056
+ $_state.addOperands(operands);
2057
+ $_state.addAttribute("callee", SymbolRefAttr::get(callee));
2058
+ if (!callee.getFunctionType().isVoid())
2059
+ $_state.addTypes(callee.getFunctionType().getReturnType());
2060
+ }]>,
2061
+ OpBuilder<(ins "Value":$ind_target,
2062
+ "FuncType":$fn_type,
2063
+ CArg<"ValueRange", "{}">:$operands), [{
2064
+ $_state.addOperands(ValueRange{ind_target});
2065
+ $_state.addOperands(operands);
2066
+ if (!fn_type.isVoid())
2067
+ $_state.addTypes(fn_type.getReturnType());
2068
+ }]>,
2069
+ OpBuilder<(ins "SymbolRefAttr":$callee, "mlir::Type":$resType,
2070
+ CArg<"ValueRange", "{}">:$operands), [{
2071
+ $_state.addOperands(operands);
2072
+ $_state.addAttribute("callee", callee);
2073
+ $_state.addTypes(resType);
2074
+ }]>];
2002
2075
}
2003
2076
2004
2077
//===----------------------------------------------------------------------===//
@@ -2386,29 +2459,33 @@ def IterEndOp : CIR_Op<"iterator_end"> {
2386
2459
}
2387
2460
2388
2461
//===----------------------------------------------------------------------===//
2389
- // FAbsOp
2462
+ // Floating Point Ops
2390
2463
//===----------------------------------------------------------------------===//
2391
2464
2392
- def FAbsOp : CIR_Op<"fabs", [Pure, SameOperandsAndResultType]> {
2465
+ class UnaryFPToFPBuiltinOp<string mnemonic>
2466
+ : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
2393
2467
let arguments = (ins AnyFloat:$src);
2394
2468
let results = (outs AnyFloat:$result);
2395
- let summary = "Returns absolute value for floating-point input.";
2396
- let description = [{
2397
- Equivalent to libc's `fabs` and LLVM's intrinsic with the same name.
2398
-
2399
- Examples:
2400
-
2401
- ```mlir
2402
- %1 = cir.const(1.0 : f64) : f64
2403
- %2 = cir.fabs %1 : f64
2404
- ```
2405
- }];
2406
-
2407
- let assemblyFormat = [{
2408
- $src `:` type($src) attr-dict
2409
- }];
2410
- let hasVerifier = 0;
2411
- }
2469
+ let summary = "libc builtin equivalent ignoring "
2470
+ "floating point exceptions and errno";
2471
+ let assemblyFormat = "$src `:` type($src) attr-dict";
2472
+ }
2473
+
2474
+ def CeilOp : UnaryFPToFPBuiltinOp<"ceil">;
2475
+ def CosOp : UnaryFPToFPBuiltinOp<"cos">;
2476
+ def ExpOp : UnaryFPToFPBuiltinOp<"exp">;
2477
+ def Exp2Op : UnaryFPToFPBuiltinOp<"exp2">;
2478
+ def FloorOp : UnaryFPToFPBuiltinOp<"floor">;
2479
+ def FAbsOp : UnaryFPToFPBuiltinOp<"fabs">;
2480
+ def LogOp : UnaryFPToFPBuiltinOp<"log">;
2481
+ def Log10Op : UnaryFPToFPBuiltinOp<"log10">;
2482
+ def Log2Op : UnaryFPToFPBuiltinOp<"log2">;
2483
+ def NearbyintOp : UnaryFPToFPBuiltinOp<"nearbyint">;
2484
+ def RintOp : UnaryFPToFPBuiltinOp<"rint">;
2485
+ def RoundOp : UnaryFPToFPBuiltinOp<"round">;
2486
+ def SinOp : UnaryFPToFPBuiltinOp<"sin">;
2487
+ def SqrtOp : UnaryFPToFPBuiltinOp<"sqrt">;
2488
+ def TruncOp : UnaryFPToFPBuiltinOp<"trunc">;
2412
2489
2413
2490
//===----------------------------------------------------------------------===//
2414
2491
// Variadic Operations
@@ -2573,29 +2650,11 @@ def StackRestoreOp : CIR_Op<"stack_restore"> {
2573
2650
let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))";
2574
2651
}
2575
2652
2576
- //===----------------------------------------------------------------------===//
2577
- // Operations Lowered Directly to LLVM IR
2578
- //
2579
- // These operations are hacks to get around missing features in LLVM's dialect.
2580
- // Use it sparingly and remove it once the features are added.
2581
- //===----------------------------------------------------------------------===//
2582
-
2583
- def ZeroInitConstOp : CIR_Op<"llvmir.zeroinit", [Pure]>,
2584
- Results<(outs AnyType:$result)> {
2585
- let summary = "Zero initializes a constant value of a given type";
2586
- let description = [{
2587
- This operation circumvents the lack of a zeroinitializer operation in LLVM
2588
- Dialect. It can zeroinitialize any LLVM type.
2589
- }];
2590
- let assemblyFormat = "attr-dict `:` type($result)";
2591
- let hasVerifier = 0;
2592
- }
2593
-
2594
2653
def AsmATT : I32EnumAttrCase<"x86_att", 0>;
2595
2654
def AsmIntel : I32EnumAttrCase<"x86_intel", 1>;
2596
2655
2597
2656
def AsmFlavor : I32EnumAttr<
2598
- "AsmDialect ",
2657
+ "AsmFlavor ",
2599
2658
"ATT or Intel",
2600
2659
[AsmATT, AsmIntel]> {
2601
2660
let cppNamespace = "::mlir::cir";
@@ -2605,26 +2664,57 @@ def CIR_InlineAsmOp : CIR_Op<"asm", [RecursiveMemoryEffects]> {
2605
2664
let description = [{
2606
2665
The `cir.asm` operation represents C/C++ asm inline.
2607
2666
2667
+ CIR constraints strings follow barelly the same rules that are established
2668
+ for the C level assembler constraints with several differences caused by
2669
+ clang::AsmStmt processing.
2670
+
2671
+ Thus, numbers that appears in the constraint string may also refer to:
2672
+ - the output variable index referenced by the input operands.
2673
+ - the index of early-clobber operand
2674
+
2608
2675
Example:
2609
2676
```C++
2610
- __asm__ volatile("xyz " : : : );
2611
- ```
2612
-
2677
+ __asm__("foo " : : : );
2678
+ __asm__("bar $42 %[val]" : [val] "=r" (x), "+&r"(x));
2679
+ __asm__("baz $42 %[val]" : [val] "=r" (x), "+&r"(x) : "[val]"(y));
2613
2680
```
2681
+
2614
2682
```mlir
2615
- cir.asm(x86_att, {"xyz"}) -> !void
2683
+ cir.asm(x86_att, {"foo" ""})
2684
+ cir.asm(x86_att, {"bar $$42 $0" "=r,=&r,1"})
2685
+ cir.asm(x86_att, {"baz $$42 $0" "=r,=&r,0,1"})
2616
2686
```
2617
2687
}];
2618
2688
2619
2689
let results = (outs Optional<CIR_AnyType>:$res);
2620
2690
2621
2691
let arguments = (
2622
2692
ins StrAttr:$asm_string,
2623
- AsmFlavor:$asm_flavor);
2693
+ StrAttr:$constraints,
2694
+ AsmFlavor:$asm_flavor);
2624
2695
2625
2696
let assemblyFormat = [{
2626
- `(`$asm_flavor`,` `{` $asm_string `}` `)` attr-dict `:` type($res)
2627
- }];
2697
+ `(`$asm_flavor`,` `{` $asm_string $constraints `}` `)` attr-dict
2698
+ `:` type($res)
2699
+ }];
2700
+ }
2701
+
2702
+ //===----------------------------------------------------------------------===//
2703
+ // Operations Lowered Directly to LLVM IR
2704
+ //
2705
+ // These operations are hacks to get around missing features in LLVM's dialect.
2706
+ // Use it sparingly and remove it once the features are added.
2707
+ //===----------------------------------------------------------------------===//
2708
+
2709
+ def ZeroInitConstOp : CIR_Op<"llvmir.zeroinit", [Pure]>,
2710
+ Results<(outs AnyType:$result)> {
2711
+ let summary = "Zero initializes a constant value of a given type";
2712
+ let description = [{
2713
+ This operation circumvents the lack of a zeroinitializer operation in LLVM
2714
+ Dialect. It can zeroinitialize any LLVM type.
2715
+ }];
2716
+ let assemblyFormat = "attr-dict `:` type($result)";
2717
+ let hasVerifier = 0;
2628
2718
}
2629
2719
2630
2720
#endif // MLIR_CIR_DIALECT_CIR_OPS
0 commit comments