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