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