diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -2781,56 +2781,25 @@ let results = (outs fir_CharacterType); - let parser = [{ - auto &builder = parser.getBuilder(); - mlir::Attribute val; - mlir::NamedAttrList attrs; - llvm::SMLoc trailingTypeLoc; - if (parser.parseAttribute(val, "fake", attrs)) - return mlir::failure(); - if (auto v = val.dyn_cast()) - result.attributes.push_back(builder.getNamedAttr(value(), v)); - else if (auto v = val.dyn_cast()) - result.attributes.push_back(builder.getNamedAttr(xlist(), v)); - else - return parser.emitError(parser.getCurrentLocation(), - "found an invalid constant"); - mlir::IntegerAttr sz; - mlir::Type type; - if (parser.parseLParen() || - parser.parseAttribute(sz, size(), result.attributes) || - parser.parseRParen() || - parser.getCurrentLocation(&trailingTypeLoc) || - parser.parseColonType(type)) - return mlir::failure(); - auto charTy = type.dyn_cast(); - if (!charTy) - return parser.emitError(trailingTypeLoc, - "must have character type"); - type = fir::CharacterType::get(builder.getContext(), charTy.getFKind(), - sz.getInt()); - if (!type || parser.addTypesToList(type, result.types)) - return mlir::failure(); - return mlir::success(); - }]; + let parser = "return parseStringLitOp(parser, result);"; - let printer = [{ - p << ' ' << getValue() << '('; - p << getSize().cast().getValue() << ") : "; - p.printType(getType()); - }]; + let printer = "::print(p, *this);"; - let verifier = [{ - if (getSize().cast().getValue().isNegative()) - return emitOpError("size must be non-negative"); - if (auto xl = (*this)->getAttr(xlist())) { - auto xList = xl.cast(); - for (auto a : xList) - if (!a.isa()) - return emitOpError("values in list must be integers"); - } - return mlir::success(); - }]; + let builders = [ + OpBuilder<(ins "fir::CharacterType":$inType, + "llvm::StringRef":$value, + CArg<"llvm::Optional", "{}">:$len)>, + OpBuilder<(ins "fir::CharacterType":$inType, + "llvm::ArrayRef":$xlist, + CArg<"llvm::Optional", "{}">:$len)>, + OpBuilder<(ins "fir::CharacterType":$inType, + "llvm::ArrayRef":$xlist, + CArg<"llvm::Optional", "{}">:$len)>, + OpBuilder<(ins "fir::CharacterType":$inType, + "llvm::ArrayRef":$xlist, + CArg<"llvm::Optional", "{}">:$len)>]; + + let verifier = "return ::verify(*this);"; let extraClassDeclaration = [{ static constexpr const char *size() { return "size"; } diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -1842,6 +1842,121 @@ return eleTy.cast().getFKind() != 1; } +static mlir::NamedAttribute +mkNamedIntegerAttr(mlir::OpBuilder &builder, llvm::StringRef name, int64_t v) { + assert(v > 0); + return builder.getNamedAttr( + name, builder.getIntegerAttr(builder.getIntegerType(64), v)); +} + +void fir::StringLitOp::build(mlir::OpBuilder &builder, OperationState &result, + fir::CharacterType inType, llvm::StringRef val, + llvm::Optional len) { + auto valAttr = builder.getNamedAttr(value(), builder.getStringAttr(val)); + int64_t length = len.hasValue() ? len.getValue() : inType.getLen(); + auto lenAttr = mkNamedIntegerAttr(builder, size(), length); + result.addAttributes({valAttr, lenAttr}); + result.addTypes(inType); +} + +template +static mlir::ArrayAttr convertToArrayAttr(mlir::OpBuilder &builder, + llvm::ArrayRef xlist) { + llvm::SmallVector attrs; + auto ty = builder.getIntegerType(8 * sizeof(C)); + for (auto ch : xlist) + attrs.push_back(builder.getIntegerAttr(ty, ch)); + return builder.getArrayAttr(attrs); +} + +void fir::StringLitOp::build(mlir::OpBuilder &builder, OperationState &result, + fir::CharacterType inType, + llvm::ArrayRef vlist, + llvm::Optional len) { + auto valAttr = + builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist)); + std::int64_t length = len.hasValue() ? len.getValue() : inType.getLen(); + auto lenAttr = mkNamedIntegerAttr(builder, size(), length); + result.addAttributes({valAttr, lenAttr}); + result.addTypes(inType); +} + +void fir::StringLitOp::build(mlir::OpBuilder &builder, OperationState &result, + fir::CharacterType inType, + llvm::ArrayRef vlist, + llvm::Optional len) { + auto valAttr = + builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist)); + std::int64_t length = len.hasValue() ? len.getValue() : inType.getLen(); + auto lenAttr = mkNamedIntegerAttr(builder, size(), length); + result.addAttributes({valAttr, lenAttr}); + result.addTypes(inType); +} + +void fir::StringLitOp::build(mlir::OpBuilder &builder, OperationState &result, + fir::CharacterType inType, + llvm::ArrayRef vlist, + llvm::Optional len) { + auto valAttr = + builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist)); + std::int64_t length = len.hasValue() ? len.getValue() : inType.getLen(); + auto lenAttr = mkNamedIntegerAttr(builder, size(), length); + result.addAttributes({valAttr, lenAttr}); + result.addTypes(inType); +} + +static mlir::ParseResult parseStringLitOp(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + auto &builder = parser.getBuilder(); + mlir::Attribute val; + mlir::NamedAttrList attrs; + llvm::SMLoc trailingTypeLoc; + if (parser.parseAttribute(val, "fake", attrs)) + return mlir::failure(); + if (auto v = val.dyn_cast()) + result.attributes.push_back( + builder.getNamedAttr(fir::StringLitOp::value(), v)); + else if (auto v = val.dyn_cast()) + result.attributes.push_back( + builder.getNamedAttr(fir::StringLitOp::xlist(), v)); + else + return parser.emitError(parser.getCurrentLocation(), + "found an invalid constant"); + mlir::IntegerAttr sz; + mlir::Type type; + if (parser.parseLParen() || + parser.parseAttribute(sz, fir::StringLitOp::size(), result.attributes) || + parser.parseRParen() || parser.getCurrentLocation(&trailingTypeLoc) || + parser.parseColonType(type)) + return mlir::failure(); + auto charTy = type.dyn_cast(); + if (!charTy) + return parser.emitError(trailingTypeLoc, "must have character type"); + type = fir::CharacterType::get(builder.getContext(), charTy.getFKind(), + sz.getInt()); + if (!type || parser.addTypesToList(type, result.types)) + return mlir::failure(); + return mlir::success(); +} + +static void print(mlir::OpAsmPrinter &p, fir::StringLitOp &op) { + p << ' ' << op.getValue() << '('; + p << op.getSize().cast().getValue() << ") : "; + p.printType(op.getType()); +} + +static mlir::LogicalResult verify(fir::StringLitOp &op) { + if (op.getSize().cast().getValue().isNegative()) + return op.emitOpError("size must be non-negative"); + if (auto xl = op.getOperation()->getAttr(fir::StringLitOp::xlist())) { + auto xList = xl.cast(); + for (auto a : xList) + if (!a.isa()) + return op.emitOpError("values in list must be integers"); + } + return mlir::success(); +} + //===----------------------------------------------------------------------===// // IfOp //===----------------------------------------------------------------------===//