Skip to content

Commit b795889

Browse files
authored
[mlir][LLVM] Make LLVMStructType parser rename on collision (#34)
This is a workaround for importing multiple modules into a single context. The downside of this solution is that it accepts invalid IRs where there is a redefinition of the named type, but solving that in the parser is not possible.
1 parent 5b77c4c commit b795889

File tree

5 files changed

+61
-6
lines changed

5 files changed

+61
-6
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ def LLVMStructType : LLVMType<"LLVMStruct", "struct", [
197197
ArrayRef<Type> elements,
198198
bool isPacked = false);
199199

200+
static LLVMStructType getUniquedIdentified(MLIRContext *context, StringRef name,
201+
ArrayRef<Type> elements,
202+
bool isPacked = false);
203+
200204
/// Gets or creates a literal struct with the given body in the provided
201205
/// context.
202206
static LLVMStructType getLiteral(MLIRContext *context, ArrayRef<Type> types,

mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,8 @@ Type LLVMStructType::parse(AsmParser &parser) {
249249
if (!isIdentified)
250250
return LLVMStructType::getLiteralChecked([loc] { return emitError(loc); },
251251
loc.getContext(), {}, isPacked);
252-
auto type = LLVMStructType::getIdentifiedChecked(
253-
[loc] { return emitError(loc); }, loc.getContext(), name);
254-
return trySetStructBody(type, {}, isPacked, parser, kwLoc);
252+
auto type = LLVMStructType::getUniquedIdentified(loc.getContext(), name, {}, isPacked);
253+
return type;
255254
}
256255

257256
// Parse subtypes. For identified structs, put the identifier of the struct on
@@ -272,9 +271,15 @@ Type LLVMStructType::parse(AsmParser &parser) {
272271
if (!isIdentified)
273272
return LLVMStructType::getLiteralChecked(
274273
[loc] { return emitError(loc); }, loc.getContext(), subtypes, isPacked);
275-
auto type = LLVMStructType::getIdentifiedChecked(
276-
[loc] { return emitError(loc); }, loc.getContext(), name);
277-
return trySetStructBody(type, subtypes, isPacked, parser, subtypesLoc);
274+
for (Type t : subtypes) {
275+
if (!LLVMStructType::isValidElementType(t)) {
276+
parser.emitError(subtypesLoc)
277+
<< "invalid LLVM structure element type: " << t;
278+
return LLVMStructType();
279+
}
280+
}
281+
auto type = LLVMStructType::getUniquedIdentified(loc.getContext(), name, subtypes, isPacked);
282+
return type;
278283
}
279284

280285
/// Parses a type appearing inside another LLVM dialect-compatible type. This

mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,22 @@ LLVMStructType LLVMStructType::getIdentifiedChecked(
435435
return Base::getChecked(emitError, context, name, /*opaque=*/false);
436436
}
437437

438+
LLVMStructType LLVMStructType::getUniquedIdentified(MLIRContext *context,
439+
StringRef name,
440+
ArrayRef<Type> elements,
441+
bool isPacked) {
442+
std::string stringName = name.str();
443+
unsigned counter = 1;
444+
do {
445+
auto type = LLVMStructType::getIdentified(context, stringName);
446+
if (failed(type.setBody(elements, isPacked))) {
447+
stringName = (Twine(name) + "." + Twine(counter++)).str();
448+
continue;
449+
}
450+
return type;
451+
} while (true);
452+
}
453+
438454
LLVMStructType LLVMStructType::getNewIdentified(MLIRContext *context,
439455
StringRef name,
440456
ArrayRef<Type> elements,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: mlir-opt %s -o - | FileCheck %s
2+
3+
module {
4+
llvm.func @foo(%arg0: i32) -> i32 attributes {dso_local} {
5+
%0 = llvm.mlir.constant(1 : i32) : i32
6+
%1 = llvm.mlir.constant(0 : i32) : i32
7+
// CHECK: !llvm.struct<"struct.S", (i32)>
8+
%2 = llvm.alloca %0 x !llvm.struct<"struct.S", (i32)> {alignment = 4 : i64} : (i32) -> !llvm.ptr
9+
%3 = llvm.getelementptr inbounds %2[%1, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.S", (i32)>
10+
llvm.store %arg0, %3 {alignment = 4 : i64} : i32, !llvm.ptr
11+
%4 = llvm.getelementptr inbounds %2[%1, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.S", (i32)>
12+
%5 = llvm.load %4 {alignment = 4 : i64} : !llvm.ptr -> i32
13+
llvm.return %5 : i32
14+
}
15+
}
16+
17+
module {
18+
llvm.func @getX(%arg0: !llvm.struct<"struct.S", (i32, i1, i32)>) -> i32 attributes {dso_local} {
19+
%0 = llvm.mlir.constant(1 : i32) : i32
20+
%1 = llvm.mlir.constant(0 : i32) : i32
21+
// CHECK: !llvm.struct<"struct.S.1", (i32, i1, i32)>
22+
%2 = llvm.alloca %0 x !llvm.struct<"struct.S", (i32, i1, i32)> {alignment = 4 : i64} : (i32) -> !llvm.ptr
23+
%3 = llvm.getelementptr inbounds %2[%1, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.S", (i32, i1, i32)>
24+
llvm.store %arg0, %3 {alignment = 4 : i64} : !llvm.struct<"struct.S", (i32, i1, i32)>, !llvm.ptr
25+
%4 = llvm.getelementptr inbounds %2[%1, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.S", (i32, i1, i32)>
26+
%5 = llvm.load %4 {alignment = 4 : i64} : !llvm.ptr -> i32
27+
llvm.return %5 : i32
28+
}
29+
}

mlir/test/Dialect/LLVMIR/types-invalid.mlir

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: mlir-opt --allow-unregistered-dialect -split-input-file -verify-diagnostics %s
2+
// REQUIRES: modified-named-struct-type-parser
23

34
func.func @array_of_void() {
45
// expected-error @+1 {{invalid array element type}}

0 commit comments

Comments
 (0)