diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 598cc7e1c541..45bd1a8ebb8f 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -46,7 +46,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { mlir::Value getConstAPSInt(mlir::Location loc, const llvm::APSInt &val) { auto ty = cir::IntType::get(getContext(), val.getBitWidth(), val.isSigned()); - return create(loc, getAttr(ty, val)); + return create(loc, cir::IntAttr::get(ty, val)); } mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits) { @@ -63,7 +63,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val) { - return create(loc, getAttr(typ, val)); + return create(loc, cir::IntAttr::get(typ, val)); } cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) { diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h index cf7a4a8ccc95..58ea67b2248d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h @@ -24,6 +24,7 @@ #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Interfaces/ASTAttrInterfaces.h" +#include "clang/CIR/Interfaces/CIRTypeInterfaces.h" //===----------------------------------------------------------------------===// // CIR Dialect Attrs diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 8511aaaf31ef..da9e6ffde51d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -406,32 +406,71 @@ def ConstRecordAttr : CIR_Attr<"ConstRecord", "const_record", // IntegerAttr //===----------------------------------------------------------------------===// -def IntAttr : CIR_Attr<"Int", "int", [TypedAttrInterface]> { +def CIR_IntAttr : CIR_Attr<"Int", "int", [TypedAttrInterface]> { let summary = "An Attribute containing a integer value"; let description = [{ An integer attribute is a literal attribute that represents an integral value of the specified integer type. }]; - let parameters = (ins AttributeSelfTypeParameter<"">:$type, "llvm::APInt":$value); + + let parameters = (ins + AttributeSelfTypeParameter<"", "cir::IntTypeInterface">:$type, + "llvm::APInt":$value + ); + let builders = [ AttrBuilderWithInferredContext<(ins "mlir::Type":$type, "const llvm::APInt &":$value), [{ - return $_get(type.getContext(), type, value); + return $_get(type.getContext(), + mlir::cast(type), value); }]>, AttrBuilderWithInferredContext<(ins "mlir::Type":$type, "int64_t":$value), [{ - IntType intType = mlir::cast(type); + auto intType = mlir::cast(type); mlir::APInt apValue(intType.getWidth(), value, intType.isSigned()); return $_get(intType.getContext(), intType, apValue); }]>, ]; + let extraClassDeclaration = [{ - int64_t getSInt() const { return getValue().getSExtValue(); } - uint64_t getUInt() const { return getValue().getZExtValue(); } - bool isNullValue() const { return getValue() == 0; } - uint64_t getBitWidth() const { return mlir::cast(getType()).getWidth(); } + int64_t getSInt() const; + uint64_t getUInt() const; + bool isNullValue() const; + bool isSigned() const; + bool isUnsigned() const; + uint64_t getBitWidth() const; + }]; + + let extraClassDefinition = [{ + int64_t $cppClass::getSInt() const { + return getValue().getSExtValue(); + } + + uint64_t $cppClass::getUInt() const { + return getValue().getZExtValue(); + } + + bool $cppClass::isNullValue() const { + return getValue() == 0; + } + + bool $cppClass::isSigned() const { + return mlir::cast(getType()).isSigned(); + } + + bool $cppClass::isUnsigned() const { + return mlir::cast(getType()).isUnsigned(); + } + + uint64_t $cppClass::getBitWidth() const { + return mlir::cast(getType()).getWidth(); + } + }]; + + let assemblyFormat = [{ + `<` custom($value, ref($type)) `>` }]; + let genVerifyDecl = 1; - let hasCustomAssemblyFormat = 1; } //===----------------------------------------------------------------------===// @@ -892,7 +931,7 @@ def DynamicCastInfoAttr GlobalViewAttr:$destRtti, "mlir::FlatSymbolRefAttr":$runtimeFunc, "mlir::FlatSymbolRefAttr":$badCastFunc, - IntAttr:$offsetHint); + CIR_IntAttr:$offsetHint); let builders = [ AttrBuilderWithInferredContext<(ins "GlobalViewAttr":$srcRtti, diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp index dc173bc41dd2..a8e444e87bc1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp @@ -271,8 +271,8 @@ bool ConstantAggregateBuilder::addBits(llvm::APInt Bits, uint64_t OffsetInBits, if (*FirstElemToUpdate == *LastElemToUpdate || isNull) { // All existing bits are either zero or undef. - add(CGM.getBuilder().getAttr(charTy, BitsThisChar), - OffsetInChars, /*AllowOverwrite*/ true); + add(cir::IntAttr::get(charTy, BitsThisChar), OffsetInChars, + /*AllowOverwrite*/ true); } else { cir::IntAttr CI = dyn_cast(Elems[*FirstElemToUpdate]); // In order to perform a partial update, we need the existing bitwise @@ -286,8 +286,7 @@ bool ConstantAggregateBuilder::addBits(llvm::APInt Bits, uint64_t OffsetInBits, assert((!(CI.getValue() & UpdateMask) || AllowOverwrite) && "unexpectedly overwriting bitfield"); BitsThisChar |= (CI.getValue() & ~UpdateMask); - Elems[*FirstElemToUpdate] = - CGM.getBuilder().getAttr(charTy, BitsThisChar); + Elems[*FirstElemToUpdate] = cir::IntAttr::get(charTy, BitsThisChar); } } @@ -1906,7 +1905,7 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &Value, if (mlir::isa(ty)) return builder.getCIRBoolAttr(Value.getInt().getZExtValue()); assert(mlir::isa(ty) && "expected integral type"); - return CGM.getBuilder().getAttr(ty, Value.getInt()); + return cir::IntAttr::get(ty, Value.getInt()); } case APValue::Float: { const llvm::APFloat &Init = Value.getFloat(); @@ -2018,8 +2017,8 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &Value, llvm::APSInt real = Value.getComplexIntReal(); llvm::APSInt imag = Value.getComplexIntImag(); return builder.getAttr( - complexType, builder.getAttr(complexElemTy, real), - builder.getAttr(complexElemTy, imag)); + complexType, cir::IntAttr::get(complexElemTy, real), + cir::IntAttr::get(complexElemTy, imag)); } assert(isa(complexElemTy) && diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index d73e1745a9c4..abe3686bceff 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -178,9 +178,8 @@ class ScalarExprEmitter : public StmtVisitor { // Leaves. mlir::Value VisitIntegerLiteral(const IntegerLiteral *E) { mlir::Type Ty = CGF.convertType(E->getType()); - return Builder.create( - CGF.getLoc(E->getExprLoc()), - Builder.getAttr(Ty, E->getValue())); + return Builder.getConstAPInt(CGF.getLoc(E->getExprLoc()), Ty, + E->getValue()); } mlir::Value VisitFixedPointLiteral(const FixedPointLiteral *E) { diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index b588ba1b96f7..30cc71d7b234 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -26,6 +26,7 @@ #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" +#include "clang/CIR/Interfaces/CIRTypeInterfaces.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/TypeSwitch.h" @@ -33,11 +34,32 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SMLoc.h" + +//===-----------------------------------------------------------------===// +// RecordMembers +//===-----------------------------------------------------------------===// static void printRecordMembers(mlir::AsmPrinter &p, mlir::ArrayAttr members); static mlir::ParseResult parseRecordMembers(::mlir::AsmParser &parser, mlir::ArrayAttr &members); +//===-----------------------------------------------------------------===// +// IntLiteral +//===-----------------------------------------------------------------===// + +static void printIntLiteral(mlir::AsmPrinter &p, llvm::APInt value, + cir::IntTypeInterface ty); + +static mlir::ParseResult parseIntLiteral(mlir::AsmParser &parser, + llvm::APInt &value, + cir::IntTypeInterface ty); + +//===-----------------------------------------------------------------===// +// FloatLiteral +//===-----------------------------------------------------------------===// + static void printFloatLiteral(mlir::AsmPrinter &p, llvm::APFloat value, mlir::Type ty); static mlir::ParseResult @@ -204,65 +226,52 @@ static void printConstPtr(AsmPrinter &p, mlir::IntegerAttr value) { // IntAttr definitions //===----------------------------------------------------------------------===// -Attribute IntAttr::parse(AsmParser &parser, Type odsType) { - mlir::APInt APValue; +template +static bool isTooLargeForType(const mlir::APInt &v, IntT expectedValue) { + if constexpr (std::is_signed_v) { + return v.getSExtValue() != expectedValue; + } else { + return v.getZExtValue() != expectedValue; + } +} - if (!mlir::isa(odsType)) - return {}; - auto type = mlir::cast(odsType); +template +static ParseResult parseIntLiteralImpl(mlir::AsmParser &p, llvm::APInt &value, + cir::IntTypeInterface ty) { + IntT ivalue; + const bool isSigned = ty.isSigned(); + if (p.parseInteger(ivalue)) + return p.emitError(p.getCurrentLocation(), "expected integer value"); - // Consume the '<' symbol. - if (parser.parseLess()) - return {}; + value = mlir::APInt(ty.getWidth(), ivalue, isSigned, /*implicitTrunc=*/true); + if (isTooLargeForType(value, ivalue)) - // Fetch arbitrary precision integer value. - if (type.isSigned()) { - int64_t value; - if (parser.parseInteger(value)) - parser.emitError(parser.getCurrentLocation(), "expected integer value"); - APValue = mlir::APInt(type.getWidth(), value, type.isSigned(), - /*implicitTrunc=*/true); - if (APValue.getSExtValue() != value) - parser.emitError(parser.getCurrentLocation(), + return p.emitError(p.getCurrentLocation(), "integer value too large for the given type"); - } else { - uint64_t value; - if (parser.parseInteger(value)) - parser.emitError(parser.getCurrentLocation(), "expected integer value"); - APValue = mlir::APInt(type.getWidth(), value, type.isSigned(), - /*implicitTrunc=*/true); - if (APValue.getZExtValue() != value) - parser.emitError(parser.getCurrentLocation(), - "integer value too large for the given type"); - } - // Consume the '>' symbol. - if (parser.parseGreater()) - return {}; + return success(); +} - return IntAttr::get(type, APValue); +mlir::ParseResult parseIntLiteral(mlir::AsmParser &parser, llvm::APInt &value, + cir::IntTypeInterface ty) { + if (ty.isSigned()) + return parseIntLiteralImpl(parser, value, ty); + return parseIntLiteralImpl(parser, value, ty); } -void IntAttr::print(AsmPrinter &printer) const { - auto type = mlir::cast(getType()); - printer << '<'; - if (type.isSigned()) - printer << getSInt(); +void printIntLiteral(mlir::AsmPrinter &p, llvm::APInt value, + cir::IntTypeInterface ty) { + if (ty.isSigned()) + p << value.getSExtValue(); else - printer << getUInt(); - printer << '>'; + p << value.getZExtValue(); } LogicalResult IntAttr::verify(function_ref emitError, - Type type, APInt value) { - if (!mlir::isa(type)) - return emitError() << "expected 'simple.int' type"; - - auto intType = mlir::cast(type); - if (value.getBitWidth() != intType.getWidth()) + cir::IntTypeInterface type, llvm::APInt value) { + if (value.getBitWidth() != type.getWidth()) return emitError() << "type and value bitwidth mismatch: " - << intType.getWidth() << " != " << value.getBitWidth(); - + << type.getWidth() << " != " << value.getBitWidth(); return success(); } @@ -481,8 +490,8 @@ LogicalResult GlobalAnnotationValuesAttr::verify(function_ref emitError, mlir::ArrayAttr annotations) { if (annotations.empty()) - return emitError() - << "GlobalAnnotationValuesAttr should at least have one annotation"; + return emitError() << "GlobalAnnotationValuesAttr should at least have " + "one annotation"; for (auto &entry : annotations) { auto annoEntry = ::mlir::dyn_cast(entry); diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 535a76552f2a..1cab89080acd 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -617,6 +617,11 @@ module { module { // expected-error@below {{integer value too large for the given type}} cir.global external @a = #cir.int<256> : !cir.int +} + +// ----- + +module { // expected-error@below {{integer value too large for the given type}} cir.global external @b = #cir.int<-129> : !cir.int }