From 32cdefd197c39714cca4c4526128396fa2867b09 Mon Sep 17 00:00:00 2001 From: David Olsen Date: Sat, 22 Feb 2025 22:30:56 -0800 Subject: [PATCH 1/2] [CIR] New format for function type return Change the assembly format for `cir::FuncType` from ``` !cir.func ``` to ``` !cir.func<(!argType) -> !returnType> ``` This change (1) is easier to parse because it doesn't require lookahead, (2) is consistent with the format of ClangIR `FuncOp` assembly, and (3) is consistent with function types in other MLIR dialects. Change all the tests to use or to expect the new format for function types. The contents and the semantics of `cir::FuncType` are unchanged. Only the assembly format is being changed. Functions that return `void` in C or C++ are still represented in MLIR as having no return type. Most of the changes are in `parseFuncType` and `printFuncType` and the functions they call in `CIRTypes.cpp`. A `FuncType::verify` function was added to check that an explicit return type is not `cir::VoidType`. `FuncType::isVoid()` was renamed to `FuncType::hasVoidReturn()` Some comments for `FuncType` were improved. An `llvm_unreachable` was added to `StructType::getKindAsStr` to suppress a compiler warning and to catch a memory error that corrupts the `RecordKind` field. (This was a drive-by fix and has nothing to do with the rest of this change.) --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 4 +- clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 1 + .../include/clang/CIR/Dialect/IR/CIRTypes.td | 35 +++--- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 +- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 112 ++++++++---------- .../CIR/CallConvLowering/AArch64/ptr-fields.c | 6 +- .../test/CIR/CallConvLowering/x86_64/fptrs.c | 22 ++-- clang/test/CIR/CodeGen/coro-task.cpp | 12 +- clang/test/CIR/CodeGen/derived-to-base.cpp | 10 +- clang/test/CIR/CodeGen/dtors.cpp | 2 +- clang/test/CIR/CodeGen/dynamic-cast-exact.cpp | 16 +-- clang/test/CIR/CodeGen/fun-ptr.c | 16 +-- clang/test/CIR/CodeGen/hello.c | 2 +- clang/test/CIR/CodeGen/lambda.cpp | 14 +-- clang/test/CIR/CodeGen/multi-vtable.cpp | 22 ++-- clang/test/CIR/CodeGen/no-prototype.c | 22 ++-- clang/test/CIR/CodeGen/store.c | 6 +- clang/test/CIR/CodeGen/struct.cpp | 4 +- clang/test/CIR/CodeGen/vtable-rtti.cpp | 16 +-- clang/test/CIR/CodeGen/vtt.cpp | 26 ++-- clang/test/CIR/IR/being_and_nothingness.cir | 15 +-- clang/test/CIR/IR/call-op-call-conv.cir | 6 +- clang/test/CIR/IR/call.cir | 4 +- clang/test/CIR/IR/func.cir | 2 +- clang/test/CIR/IR/invalid.cir | 8 +- .../test/CIR/Lowering/ThroughMLIR/vtable.cir | 8 +- clang/test/CIR/Lowering/call-op-call-conv.cir | 2 +- clang/test/CIR/Lowering/call.cir | 16 +-- clang/test/CIR/Lowering/func.cir | 6 +- clang/test/CIR/Lowering/globals.cir | 10 +- clang/test/CIR/Lowering/hello.cir | 2 +- 31 files changed, 211 insertions(+), 222 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 1feb631bfcdf..0cd870fafb28 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3857,7 +3857,7 @@ def CallOp : CIR_CallOp<"call", [NoRegionArguments]> { CArg<"mlir::UnitAttr", "{}">:$exception), [{ $_state.addOperands(ValueRange{ind_target}); $_state.addOperands(operands); - if (!fn_type.isVoid()) + if (!fn_type.hasVoidReturn()) $_state.addTypes(fn_type.getReturnType()); $_state.addAttribute("calling_conv", CallingConvAttr::get($_builder.getContext(), callingConv)); @@ -3943,7 +3943,7 @@ def TryCallOp : CIR_CallOp<"try_call", finalCallOperands.append(operands.begin(), operands.end()); $_state.addOperands(finalCallOperands); - if (!fn_type.isVoid()) + if (!fn_type.hasVoidReturn()) $_state.addTypes(fn_type.getReturnType()); $_state.addAttribute("calling_conv", diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h index 171ffda0b691..221090f25d9e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -154,6 +154,7 @@ class StructType case RecordKind::Struct: return "struct"; } + llvm_unreachable("Invalid value for StructType::getKind()"); } std::string getPrefixedName() { return getKindAsStr() + "." + getName().getValue().str(); diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 6f30f0188802..3a0451175f30 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -379,10 +379,10 @@ def CIR_FuncType : CIR_Type<"Func", "func"> { ```mlir !cir.func<()> - !cir.func + !cir.func<() -> !bool> !cir.func<(!s8i, !s8i)> - !cir.func - !cir.func + !cir.func<(!s8i, !s8i) -> !s32i> + !cir.func<(!s32i, ...) -> !s32i> ``` }]; @@ -390,23 +390,27 @@ def CIR_FuncType : CIR_Type<"Func", "func"> { "mlir::Type":$optionalReturnType, "bool":$varArg); // Use a custom parser to handle the optional return and argument types - // without an optional anchor. let assemblyFormat = [{ `<` custom($optionalReturnType, $inputs, $varArg) `>` }]; let builders = [ - // Construct with an actual return type or explicit !cir.void + // Create a FuncType, converting the return type from C-style to + // MLIR-style. If the given return type is `cir::VoidType`, ignore it + // and create the FuncType with no return type, which is how MLIR + // represents function types. TypeBuilderWithInferredContext<(ins "llvm::ArrayRef":$inputs, "mlir::Type":$returnType, CArg<"bool", "false">:$isVarArg), [{ - return $_get(returnType.getContext(), inputs, - mlir::isa(returnType) ? nullptr - : returnType, - isVarArg); + return $_get(returnType.getContext(), inputs, + mlir::isa(returnType) ? nullptr + : returnType, + isVarArg); }]> ]; + let genVerifyDecl = 1; + let extraClassDeclaration = [{ /// Returns whether the function is variadic. bool isVarArg() const { return getVarArg(); } @@ -417,16 +421,17 @@ def CIR_FuncType : CIR_Type<"Func", "func"> { /// Returns the number of arguments to the function. unsigned getNumInputs() const { return getInputs().size(); } - /// Returns the result type of the function as an actual return type or - /// explicit !cir.void + /// Get the C-style return type of the function, which is !cir.void if the + /// function returns nothing and the actual return type otherwise. mlir::Type getReturnType() const; - /// Returns the result type of the function as an ArrayRef, enabling better - /// integration with generic MLIR utilities. + /// Get the MLIR-style return type of the function, which is an empty + /// ArrayRef if the function returns nothing and a single-element ArrayRef + /// with the actual return type otherwise. llvm::ArrayRef getReturnTypes() const; - /// Returns whether the function returns void. - bool isVoid() const; + /// Does the fuction type return nothing? + bool hasVoidReturn() const; /// Returns a clone of this function type with the given argument /// and result types. diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 18e4adf19d53..22e144738783 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2739,15 +2739,15 @@ verifyCallCommInSymbolUses(Operation *op, SymbolTableCollection &symbolTable) { << stringifyCallingConv(callIf.getCallingConv()); // Void function must not return any results. - if (fnType.isVoid() && op->getNumResults() != 0) + if (fnType.hasVoidReturn() && op->getNumResults() != 0) return op->emitOpError("callee returns void but call has results"); // Non-void function calls must return exactly one result. - if (!fnType.isVoid() && op->getNumResults() != 1) + if (!fnType.hasVoidReturn() && op->getNumResults() != 1) return op->emitOpError("incorrect number of results for callee"); // Parent function and return value types must match. - if (!fnType.isVoid() && + if (!fnType.hasVoidReturn() && op->getResultTypes().front() != fnType.getReturnType()) { return op->emitOpError("result type mismatch: expected ") << fnType.getReturnType() << ", but provided " diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index b22b5707a793..e35d60293f41 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -937,66 +937,51 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const { // type. static mlir::ParseResult parseFuncTypeReturn(mlir::AsmParser &p, mlir::Type &optionalReturnType) { - if (succeeded(p.parseOptionalLParen())) { - // If we have already a '(', the function has no return type - optionalReturnType = {}; - return mlir::success(); + if (succeeded(p.parseOptionalArrow())) { + // `->` found. It must be followed by the return type. + return p.parseType(optionalReturnType); } - mlir::Type type; - if (p.parseType(type)) - return mlir::failure(); - if (isa(type)) - // An explicit !cir.void means also no return type. - optionalReturnType = {}; - else - // Otherwise use the actual type. - optionalReturnType = type; - return p.parseLParen(); + // Function has `void` return in C++, no return in MLIR. + optionalReturnType = {}; + return success(); } // A special pretty-printer for function returning or not a result. static void printFuncTypeReturn(mlir::AsmPrinter &p, mlir::Type optionalReturnType) { if (optionalReturnType) - p << optionalReturnType << ' '; - p << '('; + p << " -> " << optionalReturnType; } static mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, bool &isVarArg) { isVarArg = false; - // `(` `)` - if (succeeded(p.parseOptionalRParen())) + if (failed(p.parseLParen())) + return failure(); + if (succeeded(p.parseOptionalRParen())) { + // `()` empty argument list return mlir::success(); - - // `(` `...` `)` - if (succeeded(p.parseOptionalEllipsis())) { - isVarArg = true; - return p.parseRParen(); } - - // type (`,` type)* (`,` `...`)? - mlir::Type type; - if (p.parseType(type)) - return mlir::failure(); - params.push_back(type); - while (succeeded(p.parseOptionalComma())) { + do { if (succeeded(p.parseOptionalEllipsis())) { + // `...`, which must be the last thing in the list. isVarArg = true; - return p.parseRParen(); + break; + } else { + mlir::Type argType; + if (failed(p.parseType(argType))) + return failure(); + params.push_back(argType); } - if (p.parseType(type)) - return mlir::failure(); - params.push_back(type); - } - + } while (succeeded(p.parseOptionalComma())); return p.parseRParen(); } static void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, bool isVarArg) { + p << '('; llvm::interleaveComma(params, p, [&p](mlir::Type type) { p.printType(type); }); if (isVarArg) { @@ -1010,45 +995,52 @@ static void printFuncTypeArgs(mlir::AsmPrinter &p, // Use a custom parser to handle the optional return and argument types without // an optional anchor. static mlir::ParseResult parseFuncType(mlir::AsmParser &p, - mlir::Type &optionalReturnTypes, + mlir::Type &optionalReturnType, llvm::SmallVector ¶ms, bool &isVarArg) { - if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) + if (failed(parseFuncTypeArgs(p, params, isVarArg))) return failure(); - return parseFuncTypeArgs(p, params, isVarArg); + return parseFuncTypeReturn(p, optionalReturnType); } -static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnType, mlir::ArrayRef params, bool isVarArg) { - printFuncTypeReturn(p, optionalReturnTypes); printFuncTypeArgs(p, params, isVarArg); + printFuncTypeReturn(p, optionalReturnType); } -// Return the actual return type or an explicit !cir.void if the function does -// not return anything +/// Get the C-style return type of the function, which is !cir.void if the +/// function returns nothing and the actual return type otherwise. mlir::Type FuncType::getReturnType() const { - if (isVoid()) + if (hasVoidReturn()) return cir::VoidType::get(getContext()); - return static_cast(getImpl())->optionalReturnType; + return getOptionalReturnType(); } -/// Returns the result type of the function as an ArrayRef, enabling better -/// integration with generic MLIR utilities. +/// Get the MLIR-style return type of the function, which is an empty +/// ArrayRef if the function returns nothing and a single-element ArrayRef +/// with the actual return type otherwise. llvm::ArrayRef FuncType::getReturnTypes() const { - if (isVoid()) + if (hasVoidReturn()) return {}; - return static_cast(getImpl())->optionalReturnType; -} - -// Whether the function returns void -bool FuncType::isVoid() const { - auto rt = - static_cast(getImpl())->optionalReturnType; - assert(!rt || - !mlir::isa(rt) && - "The return type for a function returning void should be empty " - "instead of a real !cir.void"); - return !rt; + // Can't use getOptionalReturnType() here because llvm::ArrayRef hold a + // pointer to its elements and doesn't do lifetime extension. That would + // result in returning a pointer to a temporary that has gone out of scope. + return getImpl()->optionalReturnType; +} + +// Does the fuction type return nothing? +bool FuncType::hasVoidReturn() const { return !getOptionalReturnType(); } + +mlir::LogicalResult +FuncType::verify(llvm::function_ref emitError, + llvm::ArrayRef argTypes, mlir::Type returnType, + bool isVarArg) { + if (returnType && mlir::isa(returnType)) { + emitError() << "!cir.func cannot have an explicit 'void' return type"; + return mlir::failure(); + } + return mlir::success(); } //===----------------------------------------------------------------------===// diff --git a/clang/test/CIR/CallConvLowering/AArch64/ptr-fields.c b/clang/test/CIR/CallConvLowering/AArch64/ptr-fields.c index 8fc121e9bf9b..e5f06757c2ef 100644 --- a/clang/test/CIR/CallConvLowering/AArch64/ptr-fields.c +++ b/clang/test/CIR/CallConvLowering/AArch64/ptr-fields.c @@ -15,9 +15,9 @@ int foo(int x) { return x; } // CIR: %[[#V0:]] = cir.alloca !ty_A, !cir.ptr, [""] {alignment = 4 : i64} // CIR: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr // CIR: cir.store %arg0, %[[#V1]] : !u64i, !cir.ptr -// CIR: %[[#V2:]] = cir.get_global @foo : !cir.ptr> -// CIR: %[[#V3:]] = cir.get_member %[[#V0]][0] {name = "f"} : !cir.ptr -> !cir.ptr>> -// CIR: cir.store %[[#V2]], %[[#V3]] : !cir.ptr>, !cir.ptr>> +// CIR: %[[#V2:]] = cir.get_global @foo : !cir.ptr !s32i>> +// CIR: %[[#V3:]] = cir.get_member %[[#V0]][0] {name = "f"} : !cir.ptr -> !cir.ptr !s32i>>> +// CIR: cir.store %[[#V2]], %[[#V3]] : !cir.ptr !s32i>>, !cir.ptr !s32i>>> // CIR: cir.return // LLVM: void @passA(i64 %[[#V0:]]) diff --git a/clang/test/CIR/CallConvLowering/x86_64/fptrs.c b/clang/test/CIR/CallConvLowering/x86_64/fptrs.c index f2a7538919c2..e7d15528da19 100644 --- a/clang/test/CIR/CallConvLowering/x86_64/fptrs.c +++ b/clang/test/CIR/CallConvLowering/x86_64/fptrs.c @@ -10,10 +10,10 @@ typedef int (*myfptr)(S); int foo(S s) { return 42 + s.a; } // CHECK: cir.func {{.*@bar}} -// CHECK: %[[#V0:]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["a", init] -// CHECK: %[[#V1:]] = cir.get_global @foo : !cir.ptr> -// CHECK: %[[#V2:]] = cir.cast(bitcast, %[[#V1]] : !cir.ptr>), !cir.ptr> -// CHECK: cir.store %[[#V2]], %[[#V0]] : !cir.ptr>, !cir.ptr>> +// CHECK: %[[#V0:]] = cir.alloca !cir.ptr !s32i>>, !cir.ptr !s32i>>>, ["a", init] +// CHECK: %[[#V1:]] = cir.get_global @foo : !cir.ptr !s32i>> +// CHECK: %[[#V2:]] = cir.cast(bitcast, %[[#V1]] : !cir.ptr !s32i>>), !cir.ptr !s32i>> +// CHECK: cir.store %[[#V2]], %[[#V0]] : !cir.ptr !s32i>>, !cir.ptr !s32i>>> void bar() { myfptr a = foo; } @@ -22,15 +22,15 @@ void bar() { // CHECK: %[[#V0:]] = cir.alloca !ty_S, !cir.ptr, [""] {alignment = 4 : i64} // CHECK: %[[#V1:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr // CHECK: cir.store %arg0, %[[#V1]] : !s32i, !cir.ptr -// CHECK: %[[#V2:]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["a", init] -// CHECK: %[[#V3:]] = cir.get_global @foo : !cir.ptr> -// CHECK: %[[#V4:]] = cir.cast(bitcast, %[[#V3]] : !cir.ptr>), !cir.ptr> -// CHECK: cir.store %[[#V4]], %[[#V2]] : !cir.ptr>, !cir.ptr>> -// CHECK: %[[#V5:]] = cir.load %[[#V2]] : !cir.ptr>>, !cir.ptr> +// CHECK: %[[#V2:]] = cir.alloca !cir.ptr !s32i>>, !cir.ptr !s32i>>>, ["a", init] +// CHECK: %[[#V3:]] = cir.get_global @foo : !cir.ptr !s32i>> +// CHECK: %[[#V4:]] = cir.cast(bitcast, %[[#V3]] : !cir.ptr !s32i>>), !cir.ptr !s32i>> +// CHECK: cir.store %[[#V4]], %[[#V2]] : !cir.ptr !s32i>>, !cir.ptr !s32i>>> +// CHECK: %[[#V5:]] = cir.load %[[#V2]] : !cir.ptr !s32i>>>, !cir.ptr !s32i>> // CHECK: %[[#V6:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr), !cir.ptr // CHECK: %[[#V7:]] = cir.load %[[#V6]] : !cir.ptr, !s32i -// CHECK: %[[#V8:]] = cir.cast(bitcast, %[[#V5]] : !cir.ptr>), !cir.ptr> -// CHECK: %[[#V9:]] = cir.call %[[#V8]](%[[#V7]]) : (!cir.ptr>, !s32i) -> !s32i +// CHECK: %[[#V8:]] = cir.cast(bitcast, %[[#V5]] : !cir.ptr !s32i>>), !cir.ptr !s32i>> +// CHECK: %[[#V9:]] = cir.call %[[#V8]](%[[#V7]]) : (!cir.ptr !s32i>>, !s32i) -> !s32i // LLVM: define dso_local void @baz(i32 %0) // LLVM: %[[#V1:]] = alloca %struct.S, i64 1 diff --git a/clang/test/CIR/CodeGen/coro-task.cpp b/clang/test/CIR/CodeGen/coro-task.cpp index 01f30de810e8..c3ed24c9ea33 100644 --- a/clang/test/CIR/CodeGen/coro-task.cpp +++ b/clang/test/CIR/CodeGen/coro-task.cpp @@ -359,19 +359,19 @@ folly::coro::Task go4() { // CHECK: %17 = cir.alloca !ty_anon2E2_, !cir.ptr, ["ref.tmp1"] {alignment = 1 : i64} // Get the lambda invoker ptr via `lambda operator folly::coro::Task (*)(int const&)()` -// CHECK: %18 = cir.call @_ZZ3go4vENK3$_0cvPFN5folly4coro4TaskIiEERKiEEv(%17) : (!cir.ptr) -> !cir.ptr)>> -// CHECK: %19 = cir.unary(plus, %18) : !cir.ptr)>>, !cir.ptr)>> -// CHECK: cir.yield %19 : !cir.ptr)>> +// CHECK: %18 = cir.call @_ZZ3go4vENK3$_0cvPFN5folly4coro4TaskIiEERKiEEv(%17) : (!cir.ptr) -> !cir.ptr) -> ![[IntTask]]>> +// CHECK: %19 = cir.unary(plus, %18) : !cir.ptr) -> ![[IntTask]]>>, !cir.ptr) -> ![[IntTask]]>> +// CHECK: cir.yield %19 : !cir.ptr) -> ![[IntTask]]>> // CHECK: } -// CHECK: cir.store %12, %3 : !cir.ptr)>>, !cir.ptr)>>> +// CHECK: cir.store %12, %3 : !cir.ptr) -> ![[IntTask]]>>, !cir.ptr) -> ![[IntTask]]>>> // CHECK: cir.scope { // CHECK: %17 = cir.alloca !s32i, !cir.ptr, ["ref.tmp2", init] {alignment = 4 : i64} -// CHECK: %18 = cir.load %3 : !cir.ptr)>>>, !cir.ptr)>> +// CHECK: %18 = cir.load %3 : !cir.ptr) -> ![[IntTask]]>>>, !cir.ptr) -> ![[IntTask]]>> // CHECK: %19 = cir.const #cir.int<3> : !s32i // CHECK: cir.store %19, %17 : !s32i, !cir.ptr // Call invoker, which calls operator() indirectly. -// CHECK: %20 = cir.call %18(%17) : (!cir.ptr)>>, !cir.ptr) -> ![[IntTask]] +// CHECK: %20 = cir.call %18(%17) : (!cir.ptr) -> ![[IntTask]]>>, !cir.ptr) -> ![[IntTask]] // CHECK: cir.store %20, %4 : ![[IntTask]], !cir.ptr // CHECK: } diff --git a/clang/test/CIR/CodeGen/derived-to-base.cpp b/clang/test/CIR/CodeGen/derived-to-base.cpp index 879d09f58c34..c6dc92d3ac7b 100644 --- a/clang/test/CIR/CodeGen/derived-to-base.cpp +++ b/clang/test/CIR/CodeGen/derived-to-base.cpp @@ -118,11 +118,11 @@ void vcall(C1 &c1) { // CHECK: %5 = cir.load %2 : !cir.ptr, !s32i // CHECK: cir.call @_ZN5buffyC2ERKS_(%3, %1) : (!cir.ptr, !cir.ptr) -> () // CHECK: %6 = cir.load %3 : !cir.ptr, !ty_buffy -// CHECK: %7 = cir.cast(bitcast, %4 : !cir.ptr), !cir.ptr, !s32i, !ty_buffy)>>>> -// CHECK: %8 = cir.load %7 : !cir.ptr, !s32i, !ty_buffy)>>>>, !cir.ptr, !s32i, !ty_buffy)>>> -// CHECK: %9 = cir.vtable.address_point( %8 : !cir.ptr, !s32i, !ty_buffy)>>>, vtable_index = 0, address_point_index = 2) : !cir.ptr, !s32i, !ty_buffy)>>> -// CHECK: %10 = cir.load align(8) %9 : !cir.ptr, !s32i, !ty_buffy)>>>, !cir.ptr, !s32i, !ty_buffy)>> -// CHECK: %11 = cir.call %10(%4, %5, %6) : (!cir.ptr, !s32i, !ty_buffy)>>, !cir.ptr, !s32i, !ty_buffy) -> !s32i +// CHECK: %7 = cir.cast(bitcast, %4 : !cir.ptr), !cir.ptr, !s32i, !ty_buffy) -> !s32i>>>> +// CHECK: %8 = cir.load %7 : !cir.ptr, !s32i, !ty_buffy) -> !s32i>>>>, !cir.ptr, !s32i, !ty_buffy) -> !s32i>>> +// CHECK: %9 = cir.vtable.address_point( %8 : !cir.ptr, !s32i, !ty_buffy) -> !s32i>>>, vtable_index = 0, address_point_index = 2) : !cir.ptr, !s32i, !ty_buffy) -> !s32i>>> +// CHECK: %10 = cir.load align(8) %9 : !cir.ptr, !s32i, !ty_buffy) -> !s32i>>>, !cir.ptr, !s32i, !ty_buffy) -> !s32i>> +// CHECK: %11 = cir.call %10(%4, %5, %6) : (!cir.ptr, !s32i, !ty_buffy) -> !s32i>>, !cir.ptr, !s32i, !ty_buffy) -> !s32i // CHECK: cir.return // CHECK: } diff --git a/clang/test/CIR/CodeGen/dtors.cpp b/clang/test/CIR/CodeGen/dtors.cpp index 60c330d53b78..f432d61d86c4 100644 --- a/clang/test/CIR/CodeGen/dtors.cpp +++ b/clang/test/CIR/CodeGen/dtors.cpp @@ -36,7 +36,7 @@ class B : public A }; // Class A -// CHECK: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.record.decl.ast> +// CHECK: ![[ClassA:ty_.*]] = !cir.struct !u32i>>>} #cir.record.decl.ast> // Class B // CHECK: ![[ClassB:ty_.*]] = !cir.struct diff --git a/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp b/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp index cf5a9f9f6f64..829a3829ccd1 100644 --- a/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp +++ b/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp @@ -16,10 +16,10 @@ struct Derived final : Base1 {}; Derived *ptr_cast(Base1 *ptr) { return dynamic_cast(ptr); // CHECK: %[[#SRC:]] = cir.load %{{.+}} : !cir.ptr>, !cir.ptr - // CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, vtable_index = 0, address_point_index = 2) : !cir.ptr>> - // CHECK-NEXT: %[[#SRC_VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr), !cir.ptr>>> - // CHECK-NEXT: %[[#SRC_VPTR:]] = cir.load %[[#SRC_VPTR_PTR]] : !cir.ptr>>>, !cir.ptr>> - // CHECK-NEXT: %[[#SUCCESS:]] = cir.cmp(eq, %[[#SRC_VPTR]], %[[#EXPECTED_VPTR]]) : !cir.ptr>>, !cir.bool + // CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> + // CHECK-NEXT: %[[#SRC_VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr), !cir.ptr !u32i>>>> + // CHECK-NEXT: %[[#SRC_VPTR:]] = cir.load %[[#SRC_VPTR_PTR]] : !cir.ptr !u32i>>>>, !cir.ptr !u32i>>> + // CHECK-NEXT: %[[#SUCCESS:]] = cir.cmp(eq, %[[#SRC_VPTR]], %[[#EXPECTED_VPTR]]) : !cir.ptr !u32i>>>, !cir.bool // CHECK-NEXT: %{{.+}} = cir.ternary(%[[#SUCCESS]], true { // CHECK-NEXT: %[[#RES:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr), !cir.ptr // CHECK-NEXT: cir.yield %[[#RES]] : !cir.ptr @@ -39,10 +39,10 @@ Derived *ptr_cast(Base1 *ptr) { Derived &ref_cast(Base1 &ref) { return dynamic_cast(ref); // CHECK: %[[#SRC:]] = cir.load %{{.+}} : !cir.ptr>, !cir.ptr - // CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, vtable_index = 0, address_point_index = 2) : !cir.ptr>> - // CHECK-NEXT: %[[#SRC_VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr), !cir.ptr>>> - // CHECK-NEXT: %[[#SRC_VPTR:]] = cir.load %[[#SRC_VPTR_PTR]] : !cir.ptr>>>, !cir.ptr>> - // CHECK-NEXT: %[[#SUCCESS:]] = cir.cmp(eq, %[[#SRC_VPTR]], %[[#EXPECTED_VPTR]]) : !cir.ptr>>, !cir.bool + // CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> + // CHECK-NEXT: %[[#SRC_VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr), !cir.ptr !u32i>>>> + // CHECK-NEXT: %[[#SRC_VPTR:]] = cir.load %[[#SRC_VPTR_PTR]] : !cir.ptr !u32i>>>>, !cir.ptr !u32i>>> + // CHECK-NEXT: %[[#SUCCESS:]] = cir.cmp(eq, %[[#SRC_VPTR]], %[[#EXPECTED_VPTR]]) : !cir.ptr !u32i>>>, !cir.bool // CHECK-NEXT: %[[#FAILED:]] = cir.unary(not, %[[#SUCCESS]]) : !cir.bool, !cir.bool // CHECK-NEXT: cir.if %[[#FAILED]] { // CHECK-NEXT: cir.call @__cxa_bad_cast() : () -> () diff --git a/clang/test/CIR/CodeGen/fun-ptr.c b/clang/test/CIR/CodeGen/fun-ptr.c index 0f9a98300e32..087164c7b474 100644 --- a/clang/test/CIR/CodeGen/fun-ptr.c +++ b/clang/test/CIR/CodeGen/fun-ptr.c @@ -17,7 +17,7 @@ typedef struct A { fun_typ fun; } A; -// CIR: !ty_A = !cir.struct>)>>} #cir.record.decl.ast> +// CIR: !ty_A = !cir.struct>) -> !s32i>>} #cir.record.decl.ast> A a = {(fun_typ)0}; int extract_a(Data* d) { @@ -27,15 +27,15 @@ int extract_a(Data* d) { // CIR: cir.func {{@.*foo.*}}(%arg0: !cir.ptr // CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["d", init] // CIR: [[TMP1:%.*]] = cir.alloca !s32i, !cir.ptr, ["__retval"] -// CIR: [[TMP2:%.*]] = cir.alloca !cir.ptr)>>, !cir.ptr)>>>, ["f", init] +// CIR: [[TMP2:%.*]] = cir.alloca !cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i>>>, ["f", init] // CIR: cir.store %arg0, [[TMP0]] : !cir.ptr, !cir.ptr> -// CIR: [[TMP3:%.*]] = cir.const #cir.ptr : !cir.ptr)>> -// CIR: cir.store [[TMP3]], [[TMP2]] : !cir.ptr)>>, !cir.ptr)>>> -// CIR: [[TMP4:%.*]] = cir.get_global {{@.*extract_a.*}} : !cir.ptr)>> -// CIR: cir.store [[TMP4]], [[TMP2]] : !cir.ptr)>>, !cir.ptr)>>> -// CIR: [[TMP5:%.*]] = cir.load [[TMP2]] : !cir.ptr)>>>, !cir.ptr)>> +// CIR: [[TMP3:%.*]] = cir.const #cir.ptr : !cir.ptr) -> !s32i>> +// CIR: cir.store [[TMP3]], [[TMP2]] : !cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i>>> +// CIR: [[TMP4:%.*]] = cir.get_global {{@.*extract_a.*}} : !cir.ptr) -> !s32i>> +// CIR: cir.store [[TMP4]], [[TMP2]] : !cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i>>> +// CIR: [[TMP5:%.*]] = cir.load [[TMP2]] : !cir.ptr) -> !s32i>>>, !cir.ptr) -> !s32i>> // CIR: [[TMP6:%.*]] = cir.load [[TMP0]] : !cir.ptr>, !cir.ptr -// CIR: [[TMP7:%.*]] = cir.call [[TMP5]]([[TMP6]]) : (!cir.ptr)>>, !cir.ptr) -> !s32i +// CIR: [[TMP7:%.*]] = cir.call [[TMP5]]([[TMP6]]) : (!cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i // CIR: cir.store [[TMP7]], [[TMP1]] : !s32i, !cir.ptr // LLVM: define dso_local i32 {{@.*foo.*}}(ptr %0) diff --git a/clang/test/CIR/CodeGen/hello.c b/clang/test/CIR/CodeGen/hello.c index 8fb49131784c..3454b40afeed 100644 --- a/clang/test/CIR/CodeGen/hello.c +++ b/clang/test/CIR/CodeGen/hello.c @@ -11,7 +11,7 @@ int main (void) { // CHECK: cir.global "private" constant cir_private dsolocal @".str" = #cir.const_array<"Hello, world!\0A\00" : !cir.array> : !cir.array {alignment = 1 : i64} // CHECK: cir.func @main() -> !s32i // CHECK: %0 = cir.alloca !s32i, !cir.ptr, ["__retval"] {alignment = 4 : i64} -// CHECK: %1 = cir.get_global @printf : !cir.ptr, ...)>> +// CHECK: %1 = cir.get_global @printf : !cir.ptr, ...) -> !s32i>> // CHECK: %2 = cir.get_global @".str" : !cir.ptr> // CHECK: %3 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr // CHECK: %4 = cir.call @printf(%3) : (!cir.ptr) -> !s32i diff --git a/clang/test/CIR/CodeGen/lambda.cpp b/clang/test/CIR/CodeGen/lambda.cpp index 680cd2e122f1..59f5c5e8c3ce 100644 --- a/clang/test/CIR/CodeGen/lambda.cpp +++ b/clang/test/CIR/CodeGen/lambda.cpp @@ -207,27 +207,27 @@ int g3() { // CHECK-LABEL: @_Z2g3v() // CHECK: %0 = cir.alloca !s32i, !cir.ptr, ["__retval"] {alignment = 4 : i64} -// CHECK: %1 = cir.alloca !cir.ptr)>>, !cir.ptr)>>>, ["fn", init] {alignment = 8 : i64} +// CHECK: %1 = cir.alloca !cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i>>>, ["fn", init] {alignment = 8 : i64} // CHECK: %2 = cir.alloca !s32i, !cir.ptr, ["task", init] {alignment = 4 : i64} // 1. Use `operator int (*)(int const&)()` to retrieve the fnptr to `__invoke()`. // CHECK: %3 = cir.scope { // CHECK: %7 = cir.alloca !ty_anon2E5_, !cir.ptr, ["ref.tmp0"] {alignment = 1 : i64} -// CHECK: %8 = cir.call @_ZZ2g3vENK3$_0cvPFiRKiEEv(%7) : (!cir.ptr) -> !cir.ptr)>> -// CHECK: %9 = cir.unary(plus, %8) : !cir.ptr)>>, !cir.ptr)>> -// CHECK: cir.yield %9 : !cir.ptr)>> +// CHECK: %8 = cir.call @_ZZ2g3vENK3$_0cvPFiRKiEEv(%7) : (!cir.ptr) -> !cir.ptr) -> !s32i>> +// CHECK: %9 = cir.unary(plus, %8) : !cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i>> +// CHECK: cir.yield %9 : !cir.ptr) -> !s32i>> // CHECK: } // 2. Load ptr to `__invoke()`. -// CHECK: cir.store %3, %1 : !cir.ptr)>>, !cir.ptr)>>> +// CHECK: cir.store %3, %1 : !cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i>>> // CHECK: %4 = cir.scope { // CHECK: %7 = cir.alloca !s32i, !cir.ptr, ["ref.tmp1", init] {alignment = 4 : i64} -// CHECK: %8 = cir.load %1 : !cir.ptr)>>>, !cir.ptr)>> +// CHECK: %8 = cir.load %1 : !cir.ptr) -> !s32i>>>, !cir.ptr) -> !s32i>> // CHECK: %9 = cir.const #cir.int<3> : !s32i // CHECK: cir.store %9, %7 : !s32i, !cir.ptr // 3. Call `__invoke()`, which effectively executes `operator()`. -// CHECK: %10 = cir.call %8(%7) : (!cir.ptr)>>, !cir.ptr) -> !s32i +// CHECK: %10 = cir.call %8(%7) : (!cir.ptr) -> !s32i>>, !cir.ptr) -> !s32i // CHECK: cir.yield %10 : !s32i // CHECK: } diff --git a/clang/test/CIR/CodeGen/multi-vtable.cpp b/clang/test/CIR/CodeGen/multi-vtable.cpp index 8b709a3ddeaf..6fe6680d2ca3 100644 --- a/clang/test/CIR/CodeGen/multi-vtable.cpp +++ b/clang/test/CIR/CodeGen/multi-vtable.cpp @@ -34,14 +34,14 @@ int main() { // CIR: ![[VTableTypeMother:ty_.*]] = !cir.struct x 4>}> // CIR: ![[VTableTypeFather:ty_.*]] = !cir.struct x 3>}> // CIR: ![[VTableTypeChild:ty_.*]] = !cir.struct x 4>, !cir.array x 3>}> -// CIR: !ty_Father = !cir.struct>>} #cir.record.decl.ast> -// CIR: !ty_Mother = !cir.struct>>} #cir.record.decl.ast> +// CIR: !ty_Father = !cir.struct !u32i>>>} #cir.record.decl.ast> +// CIR: !ty_Mother = !cir.struct !u32i>>>} #cir.record.decl.ast> // CIR: !ty_Child = !cir.struct // CIR: cir.func linkonce_odr @_ZN6MotherC2Ev(%arg0: !cir.ptr -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV6Mother, vtable_index = 0, address_point_index = 2) : !cir.ptr>> -// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr>>> -// CIR: cir.store %2, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV6Mother, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> +// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr !u32i>>>> +// CIR: cir.store %2, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> // CIR: cir.return // CIR: } @@ -51,13 +51,13 @@ int main() { // LLVM-DAG: } // CIR: cir.func linkonce_odr @_ZN5ChildC2Ev(%arg0: !cir.ptr -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV5Child, vtable_index = 0, address_point_index = 2) : !cir.ptr>> -// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr>>> -// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV5Child, vtable_index = 1, address_point_index = 2) : !cir.ptr>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV5Child, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> +// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr !u32i>>>> +// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV5Child, vtable_index = 1, address_point_index = 2) : !cir.ptr !u32i>>> // CIR: %7 = cir.base_class_addr(%1 : !cir.ptr nonnull) [8] -> !cir.ptr -// CIR: %8 = cir.cast(bitcast, %7 : !cir.ptr), !cir.ptr>>> loc(#loc8) -// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> +// CIR: %8 = cir.cast(bitcast, %7 : !cir.ptr), !cir.ptr !u32i>>>> loc(#loc8) +// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> // CIR: cir.return // CIR: } diff --git a/clang/test/CIR/CodeGen/no-prototype.c b/clang/test/CIR/CodeGen/no-prototype.c index c119304ce54d..ad647de0f590 100644 --- a/clang/test/CIR/CodeGen/no-prototype.c +++ b/clang/test/CIR/CodeGen/no-prototype.c @@ -35,8 +35,8 @@ int test1(int x) { int noProto2(); int test2(int x) { return noProto2(x); - // CHECK: [[GGO:%.*]] = cir.get_global @noProto2 : !cir.ptr> - // CHECK: {{.*}} = cir.call [[GGO]](%{{[0-9]+}}) : (!cir.ptr>, !s32i) -> !s32i + // CHECK: [[GGO:%.*]] = cir.get_global @noProto2 : !cir.ptr !s32i>> + // CHECK: {{.*}} = cir.call [[GGO]](%{{[0-9]+}}) : (!cir.ptr !s32i>>, !s32i) -> !s32i } int noProto2(int x) { return x; } // CHECK: cir.func no_proto @noProto2(%arg0: !s32i {{.+}}) -> !s32i @@ -50,9 +50,9 @@ int noProto3(); int test3(int x) { // CHECK: cir.func @test3 return noProto3(x); - // CHECK: [[GGO:%.*]] = cir.get_global @noProto3 : !cir.ptr> - // CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr>), !cir.ptr> - // CHECK: {{%.*}} = cir.call [[CAST]](%{{[0-9]+}}) : (!cir.ptr>, !s32i) -> !s32i + // CHECK: [[GGO:%.*]] = cir.get_global @noProto3 : !cir.ptr !s32i>> + // CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr !s32i>>), !cir.ptr !s32i>> + // CHECK: {{%.*}} = cir.call [[CAST]](%{{[0-9]+}}) : (!cir.ptr !s32i>>, !s32i) -> !s32i } @@ -67,18 +67,18 @@ int noProto4() { return 0; } // cir.func private no_proto @noProto4() -> !s32i int test4(int x) { return noProto4(x); // Even if we know the definition, this should compile. - // CHECK: [[GGO:%.*]] = cir.get_global @noProto4 : !cir.ptr> - // CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr>), !cir.ptr> - // CHECK: {{%.*}} = cir.call [[CAST]]({{%.*}}) : (!cir.ptr>, !s32i) -> !s32i + // CHECK: [[GGO:%.*]] = cir.get_global @noProto4 : !cir.ptr !s32i>> + // CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr !s32i>>), !cir.ptr !s32i>> + // CHECK: {{%.*}} = cir.call [[CAST]]({{%.*}}) : (!cir.ptr !s32i>>, !s32i) -> !s32i } // No-proto definition followed by an incorrect call due to lack of args. int noProto5(); int test5(int x) { return noProto5(); - // CHECK: [[GGO:%.*]] = cir.get_global @noProto5 : !cir.ptr> - // CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr>), !cir.ptr> - // CHECK: {{%.*}} = cir.call [[CAST]]() : (!cir.ptr>) -> !s32i + // CHECK: [[GGO:%.*]] = cir.get_global @noProto5 : !cir.ptr !s32i>> + // CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr !s32i>>), !cir.ptr !s32i>> + // CHECK: {{%.*}} = cir.call [[CAST]]() : (!cir.ptr !s32i>>) -> !s32i } int noProto5(int x) { return x; } // CHECK: cir.func no_proto @noProto5(%arg0: !s32i {{.+}}) -> !s32i diff --git a/clang/test/CIR/CodeGen/store.c b/clang/test/CIR/CodeGen/store.c index 9a94e6578129..2d2fc6029ce9 100644 --- a/clang/test/CIR/CodeGen/store.c +++ b/clang/test/CIR/CodeGen/store.c @@ -24,7 +24,7 @@ void storeNoArgsFn() { // CHECK: cir.func {{.*@storeNoArgsFn}} // CHECK: %0 = cir.alloca -// CHECK: %1 = cir.get_global @get42 : !cir.ptr> -// CHECK: %2 = cir.cast(bitcast, %1 : !cir.ptr>), !cir.ptr> -// CHECK: cir.store %2, %0 : !cir.ptr>, !cir.ptr>> +// CHECK: %1 = cir.get_global @get42 : !cir.ptr !s32i>> +// CHECK: %2 = cir.cast(bitcast, %1 : !cir.ptr !s32i>>), !cir.ptr !s32i>> +// CHECK: cir.store %2, %0 : !cir.ptr !s32i>>, !cir.ptr !s32i>>> diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp index 91acb833a706..b3c502e66534 100644 --- a/clang/test/CIR/CodeGen/struct.cpp +++ b/clang/test/CIR/CodeGen/struct.cpp @@ -32,7 +32,7 @@ void yoyo(incomplete *i) {} // CHECK-DAG: !ty_Foo = !cir.struct // CHECK-DAG: !ty_Mandalore = !cir.struct, !s32i} #cir.record.decl.ast> // CHECK-DAG: !ty_Adv = !cir.struct -// CHECK-DAG: !ty_Entry = !cir.struct, !cir.ptr)>>}> +// CHECK-DAG: !ty_Entry = !cir.struct, !cir.ptr) -> !u32i>>}> // CHECK: cir.func linkonce_odr @_ZN3Bar6methodEv(%arg0: !cir.ptr // CHECK-NEXT: %0 = cir.alloca !cir.ptr, !cir.ptr>, ["this", init] {alignment = 8 : i64} @@ -172,4 +172,4 @@ void ppp() { Entry x; } // CHECK: cir.func linkonce_odr @_ZN5EntryC2Ev(%arg0: !cir.ptr -// CHECK: cir.get_member %1[0] {name = "procAddr"} : !cir.ptr -> !cir.ptr, !cir.ptr)>>> +// CHECK: cir.get_member %1[0] {name = "procAddr"} : !cir.ptr -> !cir.ptr, !cir.ptr) -> !u32i>>> diff --git a/clang/test/CIR/CodeGen/vtable-rtti.cpp b/clang/test/CIR/CodeGen/vtable-rtti.cpp index e11e80bd5b4f..3c8a5253c526 100644 --- a/clang/test/CIR/CodeGen/vtable-rtti.cpp +++ b/clang/test/CIR/CodeGen/vtable-rtti.cpp @@ -27,8 +27,8 @@ class B : public A // RTTI_DISABLED: ![[VTableTypeA:ty_.*]] = !cir.struct x 5>}> // Class A -// CHECK: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.record.decl.ast> -// RTTI_DISABLED: ![[ClassA:ty_.*]] = !cir.struct>>} #cir.record.decl.ast> +// CHECK: ![[ClassA:ty_.*]] = !cir.struct !u32i>>>} #cir.record.decl.ast> +// RTTI_DISABLED: ![[ClassA:ty_.*]] = !cir.struct !u32i>>>} #cir.record.decl.ast> // Class B // CHECK: ![[ClassB:ty_.*]] = !cir.struct @@ -45,9 +45,9 @@ class B : public A // CHECK: %1 = cir.load %0 : !cir.ptr>, !cir.ptr // CHECK: %2 = cir.base_class_addr(%1 : !cir.ptr nonnull) [0] -> !cir.ptr // CHECK: cir.call @_ZN1AC2Ev(%2) : (!cir.ptr) -> () -// CHECK: %3 = cir.vtable.address_point(@_ZTV1B, vtable_index = 0, address_point_index = 2) : !cir.ptr>> -// CHECK: %4 = cir.cast(bitcast, %1 : !cir.ptr), !cir.ptr>>> -// CHECK: cir.store %3, %4 : !cir.ptr>>, !cir.ptr>>> +// CHECK: %3 = cir.vtable.address_point(@_ZTV1B, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> +// CHECK: %4 = cir.cast(bitcast, %1 : !cir.ptr), !cir.ptr !u32i>>>> +// CHECK: cir.store %3, %4 : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> // CHECK: cir.return // CHECK: } @@ -73,9 +73,9 @@ class B : public A // CHECK: %0 = cir.alloca !cir.ptr, !cir.ptr>, ["this", init] {alignment = 8 : i64} // CHECK: cir.store %arg0, %0 : !cir.ptr, !cir.ptr> // CHECK: %1 = cir.load %0 : !cir.ptr>, !cir.ptr -// CHECK: %2 = cir.vtable.address_point(@_ZTV1A, vtable_index = 0, address_point_index = 2) : !cir.ptr>> -// CHECK: %3 = cir.cast(bitcast, %1 : !cir.ptr), !cir.ptr>>> -// CHECK: cir.store %2, %3 : !cir.ptr>>, !cir.ptr>>> +// CHECK: %2 = cir.vtable.address_point(@_ZTV1A, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> +// CHECK: %3 = cir.cast(bitcast, %1 : !cir.ptr), !cir.ptr !u32i>>>> +// CHECK: cir.store %2, %3 : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> // CHECK: cir.return // CHECK: } diff --git a/clang/test/CIR/CodeGen/vtt.cpp b/clang/test/CIR/CodeGen/vtt.cpp index c32e242737cf..6404f306327e 100644 --- a/clang/test/CIR/CodeGen/vtt.cpp +++ b/clang/test/CIR/CodeGen/vtt.cpp @@ -38,9 +38,9 @@ int f() { // Class A constructor // CIR: cir.func linkonce_odr @_ZN1AC2Ev(%arg0: !cir.ptr -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1A, vtable_index = 0, address_point_index = 2) : !cir.ptr>> -// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr>>> -// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1A, vtable_index = 0, address_point_index = 2) : !cir.ptr !u32i>>> +// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr !u32i>>>> +// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> // CIR: } // Vtable of Class D @@ -115,19 +115,19 @@ int f() { // CIR: %[[VTT_D_TO_C:.*]] = cir.vtt.address_point @_ZTT1D, offset = 3 -> !cir.ptr> // CIR: cir.call @_ZN1CC2Ev(%[[C_PTR]], %[[VTT_D_TO_C]]) : (!cir.ptr, !cir.ptr>) -> () -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1D, vtable_index = 0, address_point_index = 3) : !cir.ptr>> -// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr>>> -// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1D, vtable_index = 2, address_point_index = 3) : !cir.ptr>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1D, vtable_index = 0, address_point_index = 3) : !cir.ptr !u32i>>> +// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr !u32i>>>> +// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1D, vtable_index = 2, address_point_index = 3) : !cir.ptr !u32i>>> // CIR: %{{[0-9]+}} = cir.base_class_addr(%{{[0-9]+}} : !cir.ptr nonnull) [40] -> !cir.ptr -// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr>>> -// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> -// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1D, vtable_index = 1, address_point_index = 3) : !cir.ptr>> +// CIR: %{{[0-9]+}} = cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr !u32i>>>> +// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point(@_ZTV1D, vtable_index = 1, address_point_index = 3) : !cir.ptr !u32i>>> // CIR: cir.base_class_addr(%{{[0-9]+}} : !cir.ptr nonnull) [16] -> !cir.ptr -// CIR: cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr>>> -// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr>>, !cir.ptr>>> +// CIR: cir.cast(bitcast, %{{[0-9]+}} : !cir.ptr), !cir.ptr !u32i>>>> +// CIR: cir.store %{{[0-9]+}}, %{{[0-9]+}} : !cir.ptr !u32i>>>, !cir.ptr !u32i>>>> // CIR: cir.return // CIR: } @@ -174,4 +174,4 @@ namespace other { // CIR: %[[VAL_4:.*]] = cir.base_class_addr(%[[VAL_2]] : !cir.ptr nonnull) [0] -> !cir.ptr // CIR: cir.call @_ZN5other1AD2Ev(%[[VAL_4]]) : (!cir.ptr) -> () // CIR: cir.return -// CIR: } \ No newline at end of file +// CIR: } diff --git a/clang/test/CIR/IR/being_and_nothingness.cir b/clang/test/CIR/IR/being_and_nothingness.cir index 076c75a5b192..8dff3ba723b7 100644 --- a/clang/test/CIR/IR/being_and_nothingness.cir +++ b/clang/test/CIR/IR/being_and_nothingness.cir @@ -1,12 +1,12 @@ // RUN: cir-opt %s | FileCheck %s // Exercise different ways to encode a function returning void +// This test is less useful that it used to be, because a redundant `!cir.void` +// as a function return type is no longer supported. !s32i = !cir.int !f = !cir.func<()> -!f2 = !cir.func +!f2 = !cir.func<() -> !s32i> !void = !cir.void !fnptr2 = !cir.ptr> -// Try some useless !void -!fnptr3 = !cir.ptr> module { cir.func @ind2(%fnptr: !fnptr2, %a : !s32i) { // CHECK: cir.func @ind2(%arg0: !cir.ptr>, %arg1: !s32i) { @@ -16,13 +16,4 @@ module { // CHECK: cir.func @f2() { cir.return } - // Try with a lot of useless !void - cir.func @ind3(%fnptr: !fnptr3, %a : !s32i) -> !void { - // CHECK: cir.func @ind3(%arg0: !cir.ptr>, %arg1: !s32i) { - cir.return - } - cir.func @f3() -> !cir.void { - // CHECK: cir.func @f3() { - cir.return - } } diff --git a/clang/test/CIR/IR/call-op-call-conv.cir b/clang/test/CIR/IR/call-op-call-conv.cir index b47e1226e10b..bf13cb76d947 100644 --- a/clang/test/CIR/IR/call-op-call-conv.cir +++ b/clang/test/CIR/IR/call-op-call-conv.cir @@ -2,7 +2,7 @@ // RUN: FileCheck --input-file=%t.cir %s !s32i = !cir.int -!fnptr = !cir.ptr> +!fnptr = !cir.ptr !s32i>> module { cir.func @my_add(%a: !s32i, %b: !s32i) -> !s32i cc(spir_function) { @@ -22,6 +22,6 @@ module { } } -// CHECK: %{{[0-9]+}} = cir.call %arg0(%arg1) : (!cir.ptr>, !s32i) -> !s32i cc(spir_kernel) -// CHECK: %{{[0-9]+}} = cir.call %arg0(%arg1) : (!cir.ptr>, !s32i) -> !s32i cc(spir_function) +// CHECK: %{{[0-9]+}} = cir.call %arg0(%arg1) : (!cir.ptr !s32i>>, !s32i) -> !s32i cc(spir_kernel) +// CHECK: %{{[0-9]+}} = cir.call %arg0(%arg1) : (!cir.ptr !s32i>>, !s32i) -> !s32i cc(spir_function) // CHECK: %{{[0-9]+}} = cir.try_call @my_add(%{{[0-9]+}}, %{{[0-9]+}}) ^{{.+}}, ^{{.+}} : (!s32i, !s32i) -> !s32i cc(spir_function) diff --git a/clang/test/CIR/IR/call.cir b/clang/test/CIR/IR/call.cir index 0b1fc68622f8..abd2fe9ba878 100644 --- a/clang/test/CIR/IR/call.cir +++ b/clang/test/CIR/IR/call.cir @@ -1,7 +1,7 @@ // RUN: cir-opt %s | FileCheck %s !s32i = !cir.int -!fnptr = !cir.ptr> +!fnptr = !cir.ptr !s32i>> #fn_attr = #cir, optnone = #cir.optnone})> #fn_attr1 = #cir @@ -16,7 +16,7 @@ module { cir.func @ind(%fnptr: !fnptr, %a : !s32i) { %r = cir.call %fnptr(%a) : (!fnptr, !s32i) -> !s32i -// CHECK: %0 = cir.call %arg0(%arg1) : (!cir.ptr>, !s32i) -> !s32i +// CHECK: %0 = cir.call %arg0(%arg1) : (!cir.ptr !s32i>>, !s32i) -> !s32i // Check parse->pretty-print round-trip on extra() attribute %7 = cir.call @_ZNSt5arrayIiLm8192EEixEm(%a) : (!s32i) -> !s32i extra(#fn_attr1) // CHECK: %1 = cir.call @_ZNSt5arrayIiLm8192EEixEm(%arg1) : (!s32i) -> !s32i extra(#fn_attr1) diff --git a/clang/test/CIR/IR/func.cir b/clang/test/CIR/IR/func.cir index a1468e6462f4..87e21efb9e66 100644 --- a/clang/test/CIR/IR/func.cir +++ b/clang/test/CIR/IR/func.cir @@ -28,7 +28,7 @@ module { // Should parse custom assembly format. cir.func @parse_func_type() -> () { - %1 = cir.alloca !cir.ptr>, !cir.ptr>>, ["fn", init] {alignment = 8 : i64} + %1 = cir.alloca !cir.ptr !s32i>>, !cir.ptr !s32i>>>, ["fn", init] {alignment = 8 : i64} cir.return } diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index c628e3c2b46b..4249c744dcfe 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -1159,8 +1159,8 @@ cir.func @bad_long_double(%arg0 : !cir.long_double) -> () { !u8i = !cir.int !void = !cir.void -!Base = !cir.struct ()>>>}> -!Derived = !cir.struct ()>>>}>}> +!Base = !cir.struct !cir.int>>>}> +!Derived = !cir.struct !cir.int>>>}>}> module { cir.global "private" constant external @_ZTI4Base : !cir.ptr @@ -1181,8 +1181,8 @@ module { !u8i = !cir.int !void = !cir.void -!Base = !cir.struct ()>>>}> -!Derived = !cir.struct ()>>>}>}> +!Base = !cir.struct !cir.int>>>}> +!Derived = !cir.struct !cir.int>>>}>}> module { cir.global "private" constant external @_ZTI4Base : !cir.ptr diff --git a/clang/test/CIR/Lowering/ThroughMLIR/vtable.cir b/clang/test/CIR/Lowering/ThroughMLIR/vtable.cir index 66eb06629793..1cb4c0b672ae 100644 --- a/clang/test/CIR/Lowering/ThroughMLIR/vtable.cir +++ b/clang/test/CIR/Lowering/ThroughMLIR/vtable.cir @@ -13,9 +13,9 @@ !ty_anon_struct2 = !cir.struct> x 4>}> !ty_anon_struct3 = !cir.struct> x 3>}> !ty_anon_struct4 = !cir.struct> x 4>, !cir.array> x 3>}> -!ty_Father = !cir.struct ()>>>} #cir.record.decl.ast> -!ty_Mother = !cir.struct ()>>>} #cir.record.decl.ast> -!ty_Child = !cir.struct ()>>>} #cir.record.decl.ast>, !cir.struct ()>>>} #cir.record.decl.ast>} #cir.record.decl.ast> +!ty_Father = !cir.struct !cir.int>>>} #cir.record.decl.ast> +!ty_Mother = !cir.struct !cir.int>>>} #cir.record.decl.ast> +!ty_Child = !cir.struct !cir.int>>>} #cir.record.decl.ast>, !cir.struct !cir.int>>>} #cir.record.decl.ast>} #cir.record.decl.ast> module { cir.func linkonce_odr @_ZN6Mother6simpleEv(%arg0: !cir.ptr) { @@ -70,4 +70,4 @@ module { // MLIR: %{{[0-9]+}} = llvm.insertvalue %{{[0-9]+}}, %{{[0-9]+}}[2] : !llvm.array<3 x ptr> // MLIR: %{{[0-9]+}} = llvm.insertvalue %{{[0-9]+}}, %{{[0-9]+}}[1] : !llvm.struct<(array<4 x ptr>, array<3 x ptr>)> // MLIR: llvm.return %{{[0-9]+}} : !llvm.struct<(array<4 x ptr>, array<3 x ptr>)> -// MLIR: } \ No newline at end of file +// MLIR: } diff --git a/clang/test/CIR/Lowering/call-op-call-conv.cir b/clang/test/CIR/Lowering/call-op-call-conv.cir index 21e9e01c14ae..92f0028e7bae 100644 --- a/clang/test/CIR/Lowering/call-op-call-conv.cir +++ b/clang/test/CIR/Lowering/call-op-call-conv.cir @@ -2,7 +2,7 @@ // RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM !s32i = !cir.int -!fnptr = !cir.ptr> +!fnptr = !cir.ptr !s32i>> module { cir.func private @my_add(%a: !s32i, %b: !s32i) -> !s32i cc(spir_function) diff --git a/clang/test/CIR/Lowering/call.cir b/clang/test/CIR/Lowering/call.cir index ed4916d55e14..51dea3ef1008 100644 --- a/clang/test/CIR/Lowering/call.cir +++ b/clang/test/CIR/Lowering/call.cir @@ -38,11 +38,11 @@ module { } // check indirect call lowering - cir.global "private" external @fp : !cir.ptr> + cir.global "private" external @fp : !cir.ptr !s32i>> cir.func @callIndirect(%arg: !s32i) -> !s32i { - %fpp = cir.get_global @fp : !cir.ptr>> - %fp = cir.load %fpp : !cir.ptr>>, !cir.ptr> - %retval = cir.call %fp(%arg) : (!cir.ptr>, !s32i) -> !s32i + %fpp = cir.get_global @fp : !cir.ptr !s32i>>> + %fp = cir.load %fpp : !cir.ptr !s32i>>>, !cir.ptr !s32i>> + %retval = cir.call %fp(%arg) : (!cir.ptr !s32i>>, !s32i) -> !s32i cir.return %retval : !s32i } @@ -77,12 +77,12 @@ module { // LLVM-NEXT: ret i32 %1 // check indirect vararg call lowering - cir.global "private" external @varargfp : !cir.ptr> + cir.global "private" external @varargfp : !cir.ptr !s32i>> cir.func @varargCallIndirect() -> !s32i { - %fpp = cir.get_global @varargfp : !cir.ptr>> - %fp = cir.load %fpp : !cir.ptr>>, !cir.ptr> + %fpp = cir.get_global @varargfp : !cir.ptr !s32i>>> + %fp = cir.load %fpp : !cir.ptr !s32i>>>, !cir.ptr !s32i>> %zero = cir.const #cir.int<0> : !s32i - %retval = cir.call %fp(%zero, %zero) : (!cir.ptr>, !s32i, !s32i) -> !s32i + %retval = cir.call %fp(%zero, %zero) : (!cir.ptr !s32i>>, !s32i, !s32i) -> !s32i cir.return %retval : !s32i } diff --git a/clang/test/CIR/Lowering/func.cir b/clang/test/CIR/Lowering/func.cir index 76e6d4f0d181..241fdc364c02 100644 --- a/clang/test/CIR/Lowering/func.cir +++ b/clang/test/CIR/Lowering/func.cir @@ -6,11 +6,11 @@ module { cir.func no_proto private @noProto3(...) -> !s32i // MLIR: llvm.func @noProto3(...) -> i32 cir.func @test3(%arg0: !s32i) { - %3 = cir.get_global @noProto3 : !cir.ptr> + %3 = cir.get_global @noProto3 : !cir.ptr !s32i>> // MLIR: %[[#FN_PTR:]] = llvm.mlir.addressof @noProto3 : !llvm.ptr - %4 = cir.cast(bitcast, %3 : !cir.ptr>), !cir.ptr> + %4 = cir.cast(bitcast, %3 : !cir.ptr !s32i>>), !cir.ptr !s32i>> // MLIR: %[[#FUNC:]] = llvm.bitcast %[[#FN_PTR]] : !llvm.ptr to !llvm.ptr - %5 = cir.call %4(%arg0) : (!cir.ptr>, !s32i) -> !s32i + %5 = cir.call %4(%arg0) : (!cir.ptr !s32i>>, !s32i) -> !s32i // MLIR: %{{.+}} = llvm.call %[[#FUNC]](%{{.+}}) : !llvm.ptr, (i32) -> i32 cir.return } diff --git a/clang/test/CIR/Lowering/globals.cir b/clang/test/CIR/Lowering/globals.cir index 0108b56b8a7b..3f99fd102efd 100644 --- a/clang/test/CIR/Lowering/globals.cir +++ b/clang/test/CIR/Lowering/globals.cir @@ -15,7 +15,7 @@ !ty_Bar = !cir.struct !ty_StringStruct = !cir.struct, !cir.array, !cir.array} #cir.record.decl.ast> !ty_StringStructPtr = !cir.struct} #cir.record.decl.ast> -!ty_anon2E1_ = !cir.struct)>>} #cir.record.decl.ast> +!ty_anon2E1_ = !cir.struct)>>} #cir.record.decl.ast> module { cir.global external @a = #cir.int<3> : !s32i @@ -164,7 +164,7 @@ module { // MLIR: } // LLVM: @undefStruct = global %struct.Bar undef - cir.global "private" internal @Handlers = #cir.const_array<[#cir.const_struct<{#cir.global_view<@myfun> : !cir.ptr>}> : !ty_anon2E1_]> : !cir.array + cir.global "private" internal @Handlers = #cir.const_array<[#cir.const_struct<{#cir.global_view<@myfun> : !cir.ptr>}> : !ty_anon2E1_]> : !cir.array cir.func internal private @myfun(%arg0: !s32i) { %0 = cir.alloca !s32i, !cir.ptr, ["a", init] {alignment = 4 : i64} cir.store %arg0, %0 : !s32i, !cir.ptr @@ -179,10 +179,10 @@ module { %3 = cir.load %0 : !cir.ptr, !s32i %4 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr %5 = cir.ptr_stride(%4 : !cir.ptr, %3 : !s32i), !cir.ptr - %6 = cir.get_member %5[0] {name = "func"} : !cir.ptr -> !cir.ptr>> - %7 = cir.load %6 : !cir.ptr>>, !cir.ptr> + %6 = cir.get_member %5[0] {name = "func"} : !cir.ptr -> !cir.ptr>> + %7 = cir.load %6 : !cir.ptr>>, !cir.ptr> %8 = cir.load %1 : !cir.ptr, !s32i - cir.call %7(%8) : (!cir.ptr>, !s32i) -> () + cir.call %7(%8) : (!cir.ptr>, !s32i) -> () cir.return } //MLIR-LABEL: @foo diff --git a/clang/test/CIR/Lowering/hello.cir b/clang/test/CIR/Lowering/hello.cir index 868261307b87..361fa7ed36af 100644 --- a/clang/test/CIR/Lowering/hello.cir +++ b/clang/test/CIR/Lowering/hello.cir @@ -8,7 +8,7 @@ module @"/tmp/test.raw" attributes {cir.lang = #cir.lang, cir.sob = #cir.sign cir.global "private" constant internal @".str" = #cir.const_array<"Hello, world!\0A\00" : !cir.array> : !cir.array {alignment = 1 : i64} cir.func @main() -> !s32i { %0 = cir.alloca !s32i, !cir.ptr, ["__retval"] {alignment = 4 : i64} - %1 = cir.get_global @printf : !cir.ptr, ...)>> + %1 = cir.get_global @printf : !cir.ptr, ...) -> !s32i>> %2 = cir.get_global @".str" : !cir.ptr> %3 = cir.cast(array_to_ptrdecay, %2 : !cir.ptr>), !cir.ptr %4 = cir.call @printf(%3) : (!cir.ptr) -> !s32i From f57a09d03dd1cd126b586b350637593fbda9aba4 Mon Sep 17 00:00:00 2001 From: David Olsen Date: Mon, 24 Feb 2025 13:47:13 -0800 Subject: [PATCH 2/2] Add test case for FuncType::verify --- clang/test/CIR/IR/invalid.cir | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 4249c744dcfe..58178e7c0b9a 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -1490,3 +1490,13 @@ cir.func @cast0(%arg0: !s32i, %arg1: !s32i) { %1 = cir.cmp(eq, %arg0, %arg1): !s32i, !s32i cir.return } + +// ----- + +// Verify that void-returning functions have no return type listed in +// MLIR assembly. + +!s32i = !cir.int +// expected-error @below {{!cir.func cannot have an explicit 'void' return type}} +// expected-error @below {{failed to parse CIR_PointerType parameter}} +cir.global external dsolocal @vfp = #cir.ptr : !cir.ptr !cir.void>>