@@ -826,9 +826,9 @@ def fir_HasValueOp : fir_Op<"has_value", [Terminator, HasParent<"GlobalOp">]> {
826
826
let assemblyFormat = "$resval attr-dict `:` type($resval)";
827
827
}
828
828
829
- //===------------------------------------------------------------------------ ===//
829
+ //===----------------------------------------------------------------------===//
830
830
// Operations on !fir.box<T> type objects
831
- //===------------------------------------------------------------------------ ===//
831
+ //===----------------------------------------------------------------------===//
832
832
833
833
def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
834
834
let summary = "boxes a given reference and (optional) dimension information";
@@ -891,26 +891,27 @@ def fir_EmboxOp : fir_Op<"embox", [NoSideEffect, AttrSizedOperandSegments]> {
891
891
}
892
892
893
893
def fir_ReboxOp : fir_Op<"rebox", [NoSideEffect, AttrSizedOperandSegments]> {
894
- let summary = "create a box given another box and (optional) dimension information";
894
+ let summary =
895
+ "create a box given another box and (optional) dimension information";
895
896
896
897
let description = [{
897
- Create a new boxed reference value from another box. This is meant to be used
898
- when the taking a reference to part of a boxed value, or to an entire boxed value with
899
- new shape or type information.
898
+ Create a new boxed reference value from another box. This is meant to be
899
+ used when the taking a reference to part of a boxed value, or to an entire
900
+ boxed value with new shape or type information.
900
901
901
902
The new extra information can be:
902
903
- new shape information (new lower bounds, new rank, or new extents.
903
904
New rank/extents can only be provided if the original fir.box is
904
- contiguous in all dimension but maybe the first one ). The shape
905
+ contiguous in all dimension but maybe the first row ). The shape
905
906
operand must be provided to set new shape information.
906
- - new type (only for derived types). It is possible to set the dynamic type
907
- of the new box to one of the parent types of the input box dynamic type.
908
- Type parameters cannot be changed. This change is reflected in the requested
909
- result type of the new box.
907
+ - new type (only for derived types). It is possible to set the dynamic
908
+ type of the new box to one of the parent types of the input box dynamic
909
+ type. Type parameters cannot be changed. This change is reflected in
910
+ the requested result type of the new box.
910
911
911
- A slice argument can be provided to build a reference to part of a boxed value.
912
- In this case, the shape operand must be absent or be a fir.shift that can be
913
- used to provide a non default origin for the slice.
912
+ A slice argument can be provided to build a reference to part of a boxed
913
+ value. In this case, the shape operand must be absent or be a fir.shift
914
+ that can be used to provide a non default origin for the slice.
914
915
915
916
The following example illustrates creating a fir.box for x(10:33:2)
916
917
where x is described by a fir.box and has non default lower bounds,
@@ -1540,6 +1541,81 @@ def fir_ArrayModifyOp : fir_Op<"array_modify", [AttrSizedOperandSegments,
1540
1541
let verifier = [{ return ::verify(*this); }];
1541
1542
}
1542
1543
1544
+ def fir_ArrayAccessOp : fir_Op<"array_access", [AttrSizedOperandSegments,
1545
+ NoSideEffect]> {
1546
+ let summary = "Fetch the reference of an element of an array value";
1547
+
1548
+ let description = [{
1549
+ Fetch the memory reference of an element in an array value.
1550
+
1551
+ ```fortran
1552
+ real :: a(n,m)
1553
+ ...
1554
+ ... a ...
1555
+ ... a(r,s+1) ...
1556
+ ```
1557
+
1558
+ One can use `fir.array_access` to recover the implied memory reference to
1559
+ the element `a(i,j)` in an array expression `a` as shown above. It can also
1560
+ be used to recover the reference element `a(r,s+1)` in the second
1561
+ expression.
1562
+
1563
+ ```mlir
1564
+ %s = fir.shape %n, %m : (index, index) -> !fir.shape<2>
1565
+ // load the entire array 'a'
1566
+ %v = fir.array_load %a(%s) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.array<?x?xf32>
1567
+ // fetch the value of one of the array value's elements
1568
+ %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xf32>, index, index) -> !fir.ref<f32>
1569
+ ```
1570
+
1571
+ It is only possible to use `array_access` on an `array_load` result value.
1572
+ }];
1573
+
1574
+ let arguments = (ins
1575
+ fir_SequenceType:$sequence,
1576
+ Variadic<AnyCoordinateType>:$indices,
1577
+ Variadic<AnyIntegerType>:$typeparams
1578
+ );
1579
+
1580
+ let results = (outs fir_ReferenceType:$element);
1581
+
1582
+ let assemblyFormat = [{
1583
+ $sequence `,` $indices (`typeparams` $typeparams^)? attr-dict `:`
1584
+ functional-type(operands, results)
1585
+ }];
1586
+
1587
+ let verifier = "return ::verify(*this);";
1588
+ }
1589
+
1590
+ def fir_ArrayAmendOp : fir_Op<"array_amend", [NoSideEffect]> {
1591
+ let summary = "Mark an array value as having been changed by reference.";
1592
+
1593
+ let description = [{
1594
+ Marks an array value as having been changed via a reference. The reference
1595
+ into the array value is obtained via an fir.array_access op.
1596
+
1597
+ ```mlir
1598
+ // fetch the value of one of the array value's elements
1599
+ %1 = fir.array_access %v, %i, %j : (!fir.array<?x?xT>, index, index) -> !fir.ref<T>
1600
+ // modify the element by storing data using %1 as a reference
1601
+ %2 = ... %1 ...
1602
+ // mark the array value
1603
+ %new_v = fir.array_amend %v, %2 : (!fir.array<?x?xT>, !fir.ref<T>) -> !fir.array<?x?xT>
1604
+ ```
1605
+ }];
1606
+
1607
+ let arguments = (ins
1608
+ fir_SequenceType:$sequence,
1609
+ fir_ReferenceType:$memref
1610
+ );
1611
+
1612
+ let results = (outs fir_SequenceType);
1613
+
1614
+ let assemblyFormat = [{
1615
+ $sequence `,` $memref attr-dict `:` functional-type(operands, results)
1616
+ }];
1617
+ }
1618
+
1543
1619
def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store",
1544
1620
[AttrSizedOperandSegments]> {
1545
1621
let summary = "Store merged array value to memory.";
@@ -1893,19 +1969,34 @@ def fir_SliceOp : fir_Op<"slice", [NoSideEffect, AttrSizedOperandSegments]> {
1893
1969
%fld = fir.field_index component, !fir.type<t{...component:ct...}>
1894
1970
%d = fir.slice %lo, %hi, %step path %fld : (index, index, index, !fir.field) -> !fir.slice<1>
1895
1971
```
1972
+
1973
+ Projections of `!fir.char` type can be further narrowed to invariant
1974
+ substrings.
1975
+
1976
+ ```mlir
1977
+ %d = fir.slice %lo, %hi, %step substr %from, %to : (index, index, index, index, index) -> !fir.slice<1>
1978
+ ```
1896
1979
}];
1897
1980
1898
1981
let arguments = (ins
1899
- Variadic<AnyCoordinateType>:$triples,
1900
- Variadic<AnyComponentType>:$fields
1982
+ Variadic<AnyIntegerType>:$triples,
1983
+ Variadic<AnyComponentType>:$fields,
1984
+ Variadic<AnyIntegerType>:$substr
1901
1985
);
1902
1986
1903
1987
let results = (outs fir_SliceType);
1904
1988
1905
1989
let assemblyFormat = [{
1906
- $triples (`path` $fields^)? attr-dict `:` functional-type(operands, results)
1990
+ $triples (`path` $fields^)? (`substr` $substr^)? attr-dict `:`
1991
+ functional-type(operands, results)
1907
1992
}];
1908
1993
1994
+ let builders = [
1995
+ OpBuilder<(ins "mlir::ValueRange":$triples,
1996
+ CArg<"mlir::ValueRange", "llvm::None">:$fields,
1997
+ CArg<"mlir::ValueRange", "llvm::None">:$substr)>
1998
+ ];
1999
+
1909
2000
let verifier = "return ::verify(*this);";
1910
2001
1911
2002
let extraClassDeclaration = [{
0 commit comments