xref: /llvm-project/clang/lib/CIR/Dialect/IR/CIRDialect.cpp (revision 8e329593313bb792592529ee825a52683108df99)
1 //===- CIRDialect.cpp - MLIR CIR ops implementation -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the CIR dialect and its operations.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/CIR/Dialect/IR/CIRDialect.h"
14 
15 #include "clang/CIR/Dialect/IR/CIRTypes.h"
16 
17 #include "mlir/Support/LogicalResult.h"
18 
19 #include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
20 
21 using namespace mlir;
22 using namespace cir;
23 
24 //===----------------------------------------------------------------------===//
25 // CIR Dialect
26 //===----------------------------------------------------------------------===//
27 
28 void cir::CIRDialect::initialize() {
29   registerTypes();
30   registerAttributes();
31   addOperations<
32 #define GET_OP_LIST
33 #include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
34       >();
35 }
36 
37 //===----------------------------------------------------------------------===//
38 // ConstantOp
39 //===----------------------------------------------------------------------===//
40 
41 static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
42                                         mlir::Attribute attrType) {
43   if (isa<cir::ConstPtrAttr>(attrType)) {
44     if (!mlir::isa<cir::PointerType>(opType))
45       return op->emitOpError(
46           "pointer constant initializing a non-pointer type");
47     return success();
48   }
49 
50   if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
51     auto at = cast<TypedAttr>(attrType);
52     if (at.getType() != opType) {
53       return op->emitOpError("result type (")
54              << opType << ") does not match value type (" << at.getType()
55              << ")";
56     }
57     return success();
58   }
59 
60   assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
61   return op->emitOpError("global with type ")
62          << cast<TypedAttr>(attrType).getType() << " not yet supported";
63 }
64 
65 LogicalResult cir::ConstantOp::verify() {
66   // ODS already generates checks to make sure the result type is valid. We just
67   // need to additionally check that the value's attribute type is consistent
68   // with the result type.
69   return checkConstantTypes(getOperation(), getType(), getValue());
70 }
71 
72 OpFoldResult cir::ConstantOp::fold(FoldAdaptor /*adaptor*/) {
73   return getValue();
74 }
75 
76 //===----------------------------------------------------------------------===//
77 // GlobalOp
78 //===----------------------------------------------------------------------===//
79 
80 static ParseResult parseConstantValue(OpAsmParser &parser,
81                                       mlir::Attribute &valueAttr) {
82   NamedAttrList attr;
83   return parser.parseAttribute(valueAttr, "value", attr);
84 }
85 
86 static void printConstant(OpAsmPrinter &p, Attribute value) {
87   p.printAttribute(value);
88 }
89 
90 mlir::LogicalResult cir::GlobalOp::verify() {
91   // Verify that the initial value, if present, is either a unit attribute or
92   // an attribute CIR supports.
93   if (getInitialValue().has_value()) {
94     if (checkConstantTypes(getOperation(), getSymType(), *getInitialValue())
95             .failed())
96       return failure();
97   }
98 
99   // TODO(CIR): Many other checks for properties that haven't been upstreamed
100   // yet.
101 
102   return success();
103 }
104 
105 void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState,
106                           llvm::StringRef sym_name, mlir::Type sym_type) {
107   odsState.addAttribute(getSymNameAttrName(odsState.name),
108                         odsBuilder.getStringAttr(sym_name));
109   odsState.addAttribute(getSymTypeAttrName(odsState.name),
110                         mlir::TypeAttr::get(sym_type));
111 }
112 
113 static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op,
114                                              TypeAttr type,
115                                              Attribute initAttr) {
116   if (!op.isDeclaration()) {
117     p << "= ";
118     // This also prints the type...
119     if (initAttr)
120       printConstant(p, initAttr);
121   } else {
122     p << ": " << type;
123   }
124 }
125 
126 static ParseResult
127 parseGlobalOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr,
128                                  Attribute &initialValueAttr) {
129   mlir::Type opTy;
130   if (parser.parseOptionalEqual().failed()) {
131     // Absence of equal means a declaration, so we need to parse the type.
132     //  cir.global @a : !cir.int<s, 32>
133     if (parser.parseColonType(opTy))
134       return failure();
135   } else {
136     // Parse constant with initializer, examples:
137     //  cir.global @y = #cir.fp<1.250000e+00> : !cir.double
138     //  cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
139     if (parseConstantValue(parser, initialValueAttr).failed())
140       return failure();
141 
142     assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
143            "Non-typed attrs shouldn't appear here.");
144     auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
145     opTy = typedAttr.getType();
146   }
147 
148   typeAttr = TypeAttr::get(opTy);
149   return success();
150 }
151 
152 //===----------------------------------------------------------------------===//
153 // FuncOp
154 //===----------------------------------------------------------------------===//
155 
156 void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
157                         StringRef name) {
158   result.addAttribute(SymbolTable::getSymbolAttrName(),
159                       builder.getStringAttr(name));
160 }
161 
162 ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
163   StringAttr nameAttr;
164   if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
165                              state.attributes))
166     return failure();
167   return success();
168 }
169 
170 void cir::FuncOp::print(OpAsmPrinter &p) {
171   p << ' ';
172   // For now the only property a function has is its name
173   p.printSymbolName(getSymName());
174 }
175 
176 // TODO(CIR): The properties of functions that require verification haven't
177 // been implemented yet.
178 mlir::LogicalResult cir::FuncOp::verify() { return success(); }
179 
180 //===----------------------------------------------------------------------===//
181 // TableGen'd op method definitions
182 //===----------------------------------------------------------------------===//
183 
184 #define GET_OP_CLASSES
185 #include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
186