Skip to content

Commit 795c989

Browse files
author
Simon Camphausen
authored
[mlir][EmitC] Disallow string attributes as initial values (#75310)
1 parent 9d5b096 commit 795c989

File tree

3 files changed

+52
-34
lines changed

3 files changed

+52
-34
lines changed

mlir/lib/Dialect/EmitC/IR/EmitC.cpp

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,32 @@ void mlir::emitc::buildTerminatedBody(OpBuilder &builder, Location loc) {
5050
builder.create<emitc::YieldOp>(loc);
5151
}
5252

53+
/// Check that the type of the initial value is compatible with the operations
54+
/// result type.
55+
static LogicalResult verifyInitializationAttribute(Operation *op,
56+
Attribute value) {
57+
assert(op->getNumResults() == 1 && "operation must have 1 result");
58+
59+
if (llvm::isa<emitc::OpaqueAttr>(value))
60+
return success();
61+
62+
if (llvm::isa<StringAttr>(value))
63+
return op->emitOpError()
64+
<< "string attributes are not supported, use #emitc.opaque instead";
65+
66+
Type resultType = op->getResult(0).getType();
67+
Type attrType = cast<TypedAttr>(value).getType();
68+
69+
if (resultType != attrType)
70+
return op->emitOpError()
71+
<< "requires attribute to either be an #emitc.opaque attribute or "
72+
"it's type ("
73+
<< attrType << ") to match the op's result type (" << resultType
74+
<< ")";
75+
76+
return success();
77+
}
78+
5379
//===----------------------------------------------------------------------===//
5480
// AddOp
5581
//===----------------------------------------------------------------------===//
@@ -169,21 +195,14 @@ LogicalResult emitc::CallOpaqueOp::verify() {
169195
// ConstantOp
170196
//===----------------------------------------------------------------------===//
171197

172-
/// The constant op requires that the attribute's type matches the return type.
173198
LogicalResult emitc::ConstantOp::verify() {
174-
if (llvm::isa<emitc::OpaqueAttr>(getValueAttr()))
175-
return success();
176-
177-
// Value must not be empty
178-
StringAttr strAttr = llvm::dyn_cast<StringAttr>(getValueAttr());
179-
if (strAttr && strAttr.empty())
180-
return emitOpError() << "value must not be empty";
181-
182-
auto value = cast<TypedAttr>(getValueAttr());
183-
Type type = getType();
184-
if (!llvm::isa<NoneType>(value.getType()) && type != value.getType())
185-
return emitOpError() << "requires attribute's type (" << value.getType()
186-
<< ") to match op's return type (" << type << ")";
199+
Attribute value = getValueAttr();
200+
if (failed(verifyInitializationAttribute(getOperation(), value)))
201+
return failure();
202+
if (auto opaqueValue = llvm::dyn_cast<emitc::OpaqueAttr>(value)) {
203+
if (opaqueValue.getValue().empty())
204+
return emitOpError() << "value must not be empty";
205+
}
187206
return success();
188207
}
189208

@@ -561,17 +580,8 @@ LogicalResult SubOp::verify() {
561580
// VariableOp
562581
//===----------------------------------------------------------------------===//
563582

564-
/// The variable op requires that the attribute's type matches the return type.
565583
LogicalResult emitc::VariableOp::verify() {
566-
if (llvm::isa<emitc::OpaqueAttr>(getValueAttr()))
567-
return success();
568-
569-
auto value = cast<TypedAttr>(getValueAttr());
570-
Type type = getType();
571-
if (!llvm::isa<NoneType>(value.getType()) && type != value.getType())
572-
return emitOpError() << "requires attribute's type (" << value.getType()
573-
<< ") to match op's return type (" << type << ")";
574-
return success();
584+
return verifyInitializationAttribute(getOperation(), getValueAttr());
575585
}
576586

577587
//===----------------------------------------------------------------------===//

mlir/test/Dialect/EmitC/invalid_ops.mlir

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
// RUN: mlir-opt %s -split-input-file -verify-diagnostics
22

3+
func.func @const_attribute_str() {
4+
// expected-error @+1 {{'emitc.constant' op string attributes are not supported, use #emitc.opaque instead}}
5+
%c0 = "emitc.constant"(){value = "NULL"} : () -> !emitc.ptr<i32>
6+
return
7+
}
8+
9+
// -----
10+
311
func.func @const_attribute_return_type_1() {
4-
// expected-error @+1 {{'emitc.constant' op requires attribute's type ('i64') to match op's return type ('i32')}}
12+
// expected-error @+1 {{'emitc.constant' op requires attribute to either be an #emitc.opaque attribute or it's type ('i64') to match the op's result type ('i32')}}
513
%c0 = "emitc.constant"(){value = 42: i64} : () -> i32
614
return
715
}
816

917
// -----
1018

1119
func.func @const_attribute_return_type_2() {
12-
// expected-error @+1 {{'emitc.constant' op requires attribute's type ('!emitc.opaque<"char">') to match op's return type ('!emitc.opaque<"mychar">')}}
13-
%c0 = "emitc.constant"(){value = "CHAR_MIN" : !emitc.opaque<"char">} : () -> !emitc.opaque<"mychar">
20+
// expected-error @+1 {{'emitc.constant' op attribute 'value' failed to satisfy constraint: An opaque attribute or TypedAttr instance}}
21+
%c0 = "emitc.constant"(){value = unit} : () -> i32
1422
return
1523
}
1624

1725
// -----
1826

1927
func.func @empty_constant() {
2028
// expected-error @+1 {{'emitc.constant' op value must not be empty}}
21-
%c0 = "emitc.constant"(){value = ""} : () -> i32
29+
%c0 = "emitc.constant"(){value = #emitc.opaque<"">} : () -> i32
2230
return
2331
}
2432

@@ -98,16 +106,16 @@ func.func @illegal_operand() {
98106
// -----
99107

100108
func.func @var_attribute_return_type_1() {
101-
// expected-error @+1 {{'emitc.variable' op requires attribute's type ('i64') to match op's return type ('i32')}}
109+
// expected-error @+1 {{'emitc.variable' op requires attribute to either be an #emitc.opaque attribute or it's type ('i64') to match the op's result type ('i32')}}
102110
%c0 = "emitc.variable"(){value = 42: i64} : () -> i32
103111
return
104112
}
105113

106114
// -----
107115

108116
func.func @var_attribute_return_type_2() {
109-
// expected-error @+1 {{'emitc.variable' op requires attribute's type ('!emitc.ptr<i64>') to match op's return type ('!emitc.ptr<i32>')}}
110-
%c0 = "emitc.variable"(){value = "nullptr" : !emitc.ptr<i64>} : () -> !emitc.ptr<i32>
117+
// expected-error @+1 {{'emitc.variable' op attribute 'value' failed to satisfy constraint: An opaque attribute or TypedAttr instance}}
118+
%c0 = "emitc.variable"(){value = unit} : () -> i32
111119
return
112120
}
113121

mlir/test/Target/Cpp/const.mlir

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s -check-prefix=CPP-DECLTOP
33

44
func.func @emitc_constant() {
5-
%c0 = "emitc.constant"(){value = #emitc.opaque<"">} : () -> i32
5+
%c0 = "emitc.constant"(){value = #emitc.opaque<"INT_MAX">} : () -> i32
66
%c1 = "emitc.constant"(){value = 42 : i32} : () -> i32
77
%c2 = "emitc.constant"(){value = -1 : i32} : () -> i32
88
%c3 = "emitc.constant"(){value = -1 : si8} : () -> si8
@@ -11,7 +11,7 @@ func.func @emitc_constant() {
1111
return
1212
}
1313
// CPP-DEFAULT: void emitc_constant() {
14-
// CPP-DEFAULT-NEXT: int32_t [[V0:[^ ]*]];
14+
// CPP-DEFAULT-NEXT: int32_t [[V0:[^ ]*]] = INT_MAX;
1515
// CPP-DEFAULT-NEXT: int32_t [[V1:[^ ]*]] = 42;
1616
// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]] = -1;
1717
// CPP-DEFAULT-NEXT: int8_t [[V3:[^ ]*]] = -1;
@@ -25,7 +25,7 @@ func.func @emitc_constant() {
2525
// CPP-DECLTOP-NEXT: int8_t [[V3:[^ ]*]];
2626
// CPP-DECLTOP-NEXT: uint8_t [[V4:[^ ]*]];
2727
// CPP-DECLTOP-NEXT: char [[V5:[^ ]*]];
28-
// CPP-DECLTOP-NEXT: ;
28+
// CPP-DECLTOP-NEXT: [[V0]] = INT_MAX;
2929
// CPP-DECLTOP-NEXT: [[V1]] = 42;
3030
// CPP-DECLTOP-NEXT: [[V2]] = -1;
3131
// CPP-DECLTOP-NEXT: [[V3]] = -1;

0 commit comments

Comments
 (0)