diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index b84d5bab2eea..85493e17c915 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3474,8 +3474,6 @@ def FuncOp : CIR_Op<"func", [ /// Returns the results types that the callable region produces when /// executed. llvm::ArrayRef getCallableResults() { - if (::llvm::isa(getFunctionType().getReturnType())) - return {}; return getFunctionType().getReturnTypes(); } @@ -3492,10 +3490,15 @@ def FuncOp : CIR_Op<"func", [ } /// Returns the argument types of this function. - llvm::ArrayRef getArgumentTypes() { return getFunctionType().getInputs(); } + llvm::ArrayRef getArgumentTypes() { + return getFunctionType().getInputs(); + } - /// Returns the result types of this function. - llvm::ArrayRef getResultTypes() { return getFunctionType().getReturnTypes(); } + /// Returns 0 or 1 result type of this function (0 in the case of a function + /// returing void) + llvm::ArrayRef getResultTypes() { + return getFunctionType().getReturnTypes(); + } /// Hook for OpTrait::FunctionOpInterfaceTrait, called after verifying that /// the 'type' attribute is present and checks if it holds a function type. diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index c805b6887cf3..53ea393abe3f 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -372,29 +372,38 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", def CIR_FuncType : CIR_Type<"Func", "func"> { let summary = "CIR function type"; let description = [{ - The `!cir.func` is a function type. It consists of a single return type, a - list of parameter types and can optionally be variadic. + The `!cir.func` is a function type. It consists of an optional return type, + a list of parameter types and can optionally be variadic. Example: ```mlir + !cir.func<()> !cir.func + !cir.func<(!s8i, !s8i)> !cir.func !cir.func ``` }]; - let parameters = (ins ArrayRefParameter<"mlir::Type">:$inputs, "mlir::Type":$returnType, + let parameters = (ins ArrayRefParameter<"mlir::Type">:$inputs, + "mlir::Type":$optionalReturnType, "bool":$varArg); + // Use a custom parser to handle the optional return and argument types + // without an optional anchor. let assemblyFormat = [{ - `<` $returnType ` ` `(` custom($inputs, $varArg) `>` + `<` custom($optionalReturnType, $inputs, $varArg) `>` }]; let builders = [ + // Construct with an actual return type or explicit !cir.void TypeBuilderWithInferredContext<(ins "llvm::ArrayRef":$inputs, "mlir::Type":$returnType, CArg<"bool", "false">:$isVarArg), [{ - return $_get(returnType.getContext(), inputs, returnType, isVarArg); + return $_get(returnType.getContext(), inputs, + mlir::isa(returnType) ? nullptr + : returnType, + isVarArg); }]> ]; @@ -408,11 +417,15 @@ 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 + mlir::Type getReturnType() const; + /// Returns the result type of the function as an ArrayRef, enabling better /// integration with generic MLIR utilities. llvm::ArrayRef getReturnTypes() const; - /// Returns whether the function is returns void. + /// Returns whether the function returns void. bool isVoid() const; /// Returns a clone of this function type with the given argument diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 214b864e2bb7..916010a4f19c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -271,7 +271,7 @@ mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType QFT) { assert(QFT.isCanonical()); const Type *Ty = QFT.getTypePtr(); const FunctionType *FT = cast(QFT.getTypePtr()); - // First, check whether we can build the full fucntion type. If the function + // First, check whether we can build the full function type. If the function // type depends on an incomplete type (e.g. a struct or enum), we cannot lower // the function type. assert(isFuncTypeConvertible(FT) && "NYI"); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 5c0d01ed8fd9..a1eb11007261 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2490,13 +2490,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) { p.printSymbolName(getSymName()); auto fnType = getFunctionType(); llvm::SmallVector resultTypes; - if (!fnType.isVoid()) - function_interface_impl::printFunctionSignature( - p, *this, fnType.getInputs(), fnType.isVarArg(), - fnType.getReturnTypes()); - else - function_interface_impl::printFunctionSignature( - p, *this, fnType.getInputs(), fnType.isVarArg(), {}); + function_interface_impl::printFunctionSignature( + p, *this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes()); if (mlir::ArrayAttr annotations = getAnnotationsAttr()) { p << ' '; @@ -2565,6 +2560,11 @@ LogicalResult cir::FuncOp::verifyType() { if (!getNoProto() && type.isVarArg() && type.getNumInputs() == 0) return emitError() << "prototyped function must have at least one non-variadic input"; + if (auto rt = type.getReturnTypes(); + !rt.empty() && mlir::isa(rt.front())) + return emitOpError("The return type for a function returning void should " + "be empty instead of an explicit !cir.void"); + return success(); } diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index df89584fd3a9..04ecf52a428d 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -33,6 +33,7 @@ #include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include #include using cir::MissingFeatures; @@ -41,12 +42,13 @@ using cir::MissingFeatures; // CIR Custom Parser/Printer Signatures //===----------------------------------------------------------------------===// -static mlir::ParseResult -parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, - bool &isVarArg); -static void printFuncTypeArgs(mlir::AsmPrinter &p, - mlir::ArrayRef params, bool isVarArg); +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg); +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg); static mlir::ParseResult parsePointerAddrSpace(mlir::AsmParser &p, mlir::Attribute &addrSpaceAttr); static void printPointerAddrSpace(mlir::AsmPrinter &p, @@ -913,9 +915,38 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const { return get(llvm::to_vector(inputs), results[0], isVarArg()); } -mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p, - llvm::SmallVector ¶ms, - bool &isVarArg) { +// A special parser is needed for function returning void to handle the missing +// 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(); + } + 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(); +} + +// 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 << '('; +} + +static mlir::ParseResult +parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, + bool &isVarArg) { isVarArg = false; // `(` `)` if (succeeded(p.parseOptionalRParen())) @@ -945,8 +976,9 @@ mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p, return p.parseRParen(); } -void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, - bool isVarArg) { +static void printFuncTypeArgs(mlir::AsmPrinter &p, + mlir::ArrayRef params, + bool isVarArg) { llvm::interleaveComma(params, p, [&p](mlir::Type type) { p.printType(type); }); if (isVarArg) { @@ -957,11 +989,49 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, 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, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) + return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg) { + printFuncTypeReturn(p, optionalReturnTypes); + printFuncTypeArgs(p, params, isVarArg); +} + +// Return the actual return type or an explicit !cir.void if the function does +// not return anything +mlir::Type FuncType::getReturnType() const { + if (isVoid()) + return cir::VoidType::get(getContext()); + return static_cast(getImpl())->optionalReturnType; +} + +/// Returns the result type of the function as an ArrayRef, enabling better +/// integration with generic MLIR utilities. llvm::ArrayRef FuncType::getReturnTypes() const { - return static_cast(getImpl())->returnType; + if (isVoid()) + return {}; + return static_cast(getImpl())->optionalReturnType; } -bool FuncType::isVoid() const { return mlir::isa(getReturnType()); } +// 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; +} //===----------------------------------------------------------------------===// // MethodType Definitions diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp index 0c2233ef84c9..d655ae9023dd 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerTypes.cpp @@ -109,7 +109,7 @@ FuncType LowerTypes::getFunctionType(const LowerFunctionInfo &FI) { } } - return FuncType::get(getMLIRContext(), ArgTypes, resultType, FI.isVariadic()); + return FuncType::get(ArgTypes, resultType, FI.isVariadic()); } /// Convert a CIR type to its ABI-specific default form. diff --git a/clang/test/CIR/CodeGen/fun-ptr.c b/clang/test/CIR/CodeGen/fun-ptr.c index 7092c58e64d0..0f9a98300e32 100644 --- a/clang/test/CIR/CodeGen/fun-ptr.c +++ b/clang/test/CIR/CodeGen/fun-ptr.c @@ -55,10 +55,10 @@ int foo(Data* d) { return f(d); } -// CIR: cir.func private {{@.*test.*}}() -> !cir.ptr> +// CIR: cir.func private {{@.*test.*}}() -> !cir.ptr> // CIR: cir.func {{@.*bar.*}}() -// CIR: [[RET:%.*]] = cir.call {{@.*test.*}}() : () -> !cir.ptr> -// CIR: cir.call [[RET]]() : (!cir.ptr>) -> () +// CIR: [[RET:%.*]] = cir.call {{@.*test.*}}() : () -> !cir.ptr> +// CIR: cir.call [[RET]]() : (!cir.ptr>) -> () // CIR: cir.return // LLVM: declare ptr {{@.*test.*}}() diff --git a/clang/test/CIR/CodeGen/gnu-extension.c b/clang/test/CIR/CodeGen/gnu-extension.c index 7386de78176f..5a9f4b0b22b4 100644 --- a/clang/test/CIR/CodeGen/gnu-extension.c +++ b/clang/test/CIR/CodeGen/gnu-extension.c @@ -15,5 +15,5 @@ void bar(void) { } //CHECK: cir.func @bar() -//CHECK: {{.*}} = cir.get_global @bar : !cir.ptr> +//CHECK: {{.*}} = cir.get_global @bar : !cir.ptr> //CHECK: cir.return diff --git a/clang/test/CIR/CodeGen/member-init-struct.cpp b/clang/test/CIR/CodeGen/member-init-struct.cpp index 8440526c1a1c..4c5161616475 100644 --- a/clang/test/CIR/CodeGen/member-init-struct.cpp +++ b/clang/test/CIR/CodeGen/member-init-struct.cpp @@ -34,7 +34,7 @@ C a, b(x), c(0, 2); // CHECK: %[[VAL_8:.*]] = cir.get_member %[[VAL_2]][2] {name = "d"} : !cir.ptr -> !cir.ptr> // CHECK: %[[VAL_9:.*]] = cir.const {{.*}} : !cir.array // CHECK: cir.store %[[VAL_9]], %[[VAL_8]] : !cir.array, !cir.ptr> -// CHECK: %[[VAL_10:.*]] = cir.get_member %[[VAL_2]][4] {name = "e"} : !cir.ptr -> !cir.ptr in !ty_C>> -// CHECK: %[[VAL_11:.*]] = cir.const #cir.method : !cir.method in !ty_C> -// CHECK: cir.store %[[VAL_11]], %[[VAL_10]] : !cir.method in !ty_C>, !cir.ptr in !ty_C>> -// CHECK: cir.return \ No newline at end of file +// CHECK: %[[VAL_10:.*]] = cir.get_member %[[VAL_2]][4] {name = "e"} : !cir.ptr -> !cir.ptr in !ty_C>> +// CHECK: %[[VAL_11:.*]] = cir.const #cir.method : !cir.method in !ty_C> +// CHECK: cir.store %[[VAL_11]], %[[VAL_10]] : !cir.method in !ty_C>, !cir.ptr in !ty_C>> +// CHECK: cir.return diff --git a/clang/test/CIR/CodeGen/multi-vtable.cpp b/clang/test/CIR/CodeGen/multi-vtable.cpp index b887e78c8239..8b709a3ddeaf 100644 --- a/clang/test/CIR/CodeGen/multi-vtable.cpp +++ b/clang/test/CIR/CodeGen/multi-vtable.cpp @@ -74,9 +74,9 @@ int main() { // CIR: cir.func @main() -> !s32i extra(#fn_attr) { -// CIR: %{{[0-9]+}} = cir.vtable.address_point( %{{[0-9]+}} : !cir.ptr)>>>, vtable_index = 0, address_point_index = 0) : !cir.ptr)>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point( %{{[0-9]+}} : !cir.ptr)>>>, vtable_index = 0, address_point_index = 0) : !cir.ptr)>>> -// CIR: %{{[0-9]+}} = cir.vtable.address_point( %{{[0-9]+}} : !cir.ptr)>>>, vtable_index = 0, address_point_index = 0) : !cir.ptr)>>> +// CIR: %{{[0-9]+}} = cir.vtable.address_point( %{{[0-9]+}} : !cir.ptr)>>>, vtable_index = 0, address_point_index = 0) : !cir.ptr)>>> // CIR: } diff --git a/clang/test/CIR/CodeGen/no-proto-fun-ptr.c b/clang/test/CIR/CodeGen/no-proto-fun-ptr.c index b4d92db11963..92c3eb6516e1 100644 --- a/clang/test/CIR/CodeGen/no-proto-fun-ptr.c +++ b/clang/test/CIR/CodeGen/no-proto-fun-ptr.c @@ -7,9 +7,9 @@ void check_noproto_ptr() { } // CHECK: cir.func no_proto @check_noproto_ptr() -// CHECK: [[ALLOC:%.*]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["fun", init] {alignment = 8 : i64} -// CHECK: [[GGO:%.*]] = cir.get_global @empty : !cir.ptr> -// CHECK: cir.store [[GGO]], [[ALLOC]] : !cir.ptr>, !cir.ptr>> +// CHECK: [[ALLOC:%.*]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["fun", init] {alignment = 8 : i64} +// CHECK: [[GGO:%.*]] = cir.get_global @empty : !cir.ptr> +// CHECK: cir.store [[GGO]], [[ALLOC]] : !cir.ptr>, !cir.ptr>> // CHECK: cir.return void empty(void) {} @@ -20,8 +20,8 @@ void buz() { } // CHECK: cir.func no_proto @buz() -// CHECK: [[FNPTR_ALLOC:%.*]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["func"] {alignment = 8 : i64} -// CHECK: [[FNPTR:%.*]] = cir.load deref [[FNPTR_ALLOC]] : !cir.ptr>>, !cir.ptr> -// CHECK: [[CAST:%.*]] = cir.cast(bitcast, %1 : !cir.ptr>), !cir.ptr> -// CHECK: cir.call [[CAST]]() : (!cir.ptr>) -> () +// CHECK: [[FNPTR_ALLOC:%.*]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["func"] {alignment = 8 : i64} +// CHECK: [[FNPTR:%.*]] = cir.load deref [[FNPTR_ALLOC]] : !cir.ptr>>, !cir.ptr> +// CHECK: [[CAST:%.*]] = cir.cast(bitcast, %1 : !cir.ptr>), !cir.ptr> +// CHECK: cir.call [[CAST]]() : (!cir.ptr>) -> () // CHECK: cir.return diff --git a/clang/test/CIR/CodeGen/pointer-arith-ext.c b/clang/test/CIR/CodeGen/pointer-arith-ext.c index 558ad823cae4..c1a3d374b44b 100644 --- a/clang/test/CIR/CodeGen/pointer-arith-ext.c +++ b/clang/test/CIR/CodeGen/pointer-arith-ext.c @@ -50,9 +50,9 @@ void *f4_1(void *a, int b) { return (a -= b); } FP f5(FP a, int b) { return a + b; } // CIR-LABEL: f5 -// CIR: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr>>, !cir.ptr> +// CIR: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr>>, !cir.ptr> // CIR: %[[STRIDE:.*]] = cir.load {{.*}} : !cir.ptr, !s32i -// CIR: cir.ptr_stride(%[[PTR]] : !cir.ptr>, %[[STRIDE]] : !s32i) +// CIR: cir.ptr_stride(%[[PTR]] : !cir.ptr>, %[[STRIDE]] : !s32i) // LLVM-LABEL: f5 // LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8 @@ -67,10 +67,10 @@ FP f6_1(int a, FP b) { return (a += b); } FP f7(FP a, int b) { return a - b; } // CIR-LABEL: f7 -// CIR: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr>>, !cir.ptr> +// CIR: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr>>, !cir.ptr> // CIR: %[[STRIDE:.*]] = cir.load {{.*}} : !cir.ptr, !s32i // CIR: %[[SUB:.*]] = cir.unary(minus, %[[STRIDE]]) : !s32i, !s32i -// CIR: cir.ptr_stride(%[[PTR]] : !cir.ptr>, %[[SUB]] : !s32i) +// CIR: cir.ptr_stride(%[[PTR]] : !cir.ptr>, %[[SUB]] : !s32i) // LLVM-LABEL: f7 // LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8 diff --git a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp index 6f8b3363bfa3..f3c426c4b1ee 100644 --- a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp +++ b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp @@ -11,24 +11,24 @@ auto make_non_virtual() -> void (Foo::*)(int) { return &Foo::m1; } -// CHECK-LABEL: cir.func @_Z16make_non_virtualv() -> !cir.method in !ty_Foo> -// CHECK: %{{.+}} = cir.const #cir.method<@_ZN3Foo2m1Ei> : !cir.method in !ty_Foo> +// CHECK-LABEL: cir.func @_Z16make_non_virtualv() -> !cir.method in !ty_Foo> +// CHECK: %{{.+}} = cir.const #cir.method<@_ZN3Foo2m1Ei> : !cir.method in !ty_Foo> // CHECK: } auto make_virtual() -> void (Foo::*)(int) { return &Foo::m3; } -// CHECK-LABEL: cir.func @_Z12make_virtualv() -> !cir.method in !ty_Foo> -// CHECK: %{{.+}} = cir.const #cir.method : !cir.method in !ty_Foo> +// CHECK-LABEL: cir.func @_Z12make_virtualv() -> !cir.method in !ty_Foo> +// CHECK: %{{.+}} = cir.const #cir.method : !cir.method in !ty_Foo> // CHECK: } auto make_null() -> void (Foo::*)(int) { return nullptr; } -// CHECK-LABEL: cir.func @_Z9make_nullv() -> !cir.method in !ty_Foo> -// CHECK: %{{.+}} = cir.const #cir.method : !cir.method in !ty_Foo> +// CHECK-LABEL: cir.func @_Z9make_nullv() -> !cir.method in !ty_Foo> +// CHECK: %{{.+}} = cir.const #cir.method : !cir.method in !ty_Foo> // CHECK: } void call(Foo *obj, void (Foo::*func)(int), int arg) { @@ -36,7 +36,7 @@ void call(Foo *obj, void (Foo::*func)(int), int arg) { } // CHECK-LABEL: cir.func @_Z4callP3FooMS_FviEi -// CHECK: %[[CALLEE:.+]], %[[THIS:.+]] = cir.get_method %{{.+}}, %{{.+}} : (!cir.method in !ty_Foo>, !cir.ptr) -> (!cir.ptr, !s32i)>>, !cir.ptr) +// CHECK: %[[CALLEE:.+]], %[[THIS:.+]] = cir.get_method %{{.+}}, %{{.+}} : (!cir.method in !ty_Foo>, !cir.ptr) -> (!cir.ptr, !s32i)>>, !cir.ptr) // CHECK-NEXT: %[[#ARG:]] = cir.load %{{.+}} : !cir.ptr, !s32i -// CHECK-NEXT: cir.call %[[CALLEE]](%[[THIS]], %[[#ARG]]) : (!cir.ptr, !s32i)>>, !cir.ptr, !s32i) -> () +// CHECK-NEXT: cir.call %[[CALLEE]](%[[THIS]], %[[#ARG]]) : (!cir.ptr, !s32i)>>, !cir.ptr, !s32i) -> () // CHECK: } diff --git a/clang/test/CIR/CodeGen/static.cpp b/clang/test/CIR/CodeGen/static.cpp index 88ff490c14ff..657396845e13 100644 --- a/clang/test/CIR/CodeGen/static.cpp +++ b/clang/test/CIR/CodeGen/static.cpp @@ -40,7 +40,7 @@ static Init __ioinit2(false); // AFTER: module {{.*}} attributes {{.*}}cir.global_ctors = [#cir.global_ctor<"__cxx_global_var_init", 65536>, #cir.global_ctor<"__cxx_global_var_init.1", 65536>] // AFTER-NEXT: cir.global "private" external @__dso_handle : i8 -// AFTER-NEXT: cir.func private @__cxa_atexit(!cir.ptr)>>, !cir.ptr, !cir.ptr) +// AFTER-NEXT: cir.func private @__cxa_atexit(!cir.ptr)>>, !cir.ptr, !cir.ptr) // AFTER-NEXT: cir.func private @_ZN4InitC1Eb(!cir.ptr, !cir.bool) // AFTER-NEXT: cir.func private @_ZN4InitD1Ev(!cir.ptr) // AFTER-NEXT: cir.global "private" internal dsolocal @_ZL8__ioinit = #cir.zero : !ty_Init {alignment = 1 : i64, ast = #cir.var.decl.ast} @@ -49,11 +49,11 @@ static Init __ioinit2(false); // AFTER-NEXT: %1 = cir.const #true // AFTER-NEXT: cir.call @_ZN4InitC1Eb(%0, %1) : (!cir.ptr, !cir.bool) -> () // AFTER-NEXT: %2 = cir.get_global @_ZL8__ioinit : !cir.ptr -// AFTER-NEXT: %3 = cir.get_global @_ZN4InitD1Ev : !cir.ptr)>> -// AFTER-NEXT: %4 = cir.cast(bitcast, %3 : !cir.ptr)>>), !cir.ptr)>> +// AFTER-NEXT: %3 = cir.get_global @_ZN4InitD1Ev : !cir.ptr)>> +// AFTER-NEXT: %4 = cir.cast(bitcast, %3 : !cir.ptr)>>), !cir.ptr)>> // AFTER-NEXT: %5 = cir.cast(bitcast, %2 : !cir.ptr), !cir.ptr // AFTER-NEXT: %6 = cir.get_global @__dso_handle : !cir.ptr -// AFTER-NEXT: cir.call @__cxa_atexit(%4, %5, %6) : (!cir.ptr)>>, !cir.ptr, !cir.ptr) -> () +// AFTER-NEXT: cir.call @__cxa_atexit(%4, %5, %6) : (!cir.ptr)>>, !cir.ptr, !cir.ptr) -> () // AFTER-NEXT: cir.return // AFTER: cir.global "private" internal dsolocal @_ZL9__ioinit2 = #cir.zero : !ty_Init {alignment = 1 : i64, ast = #cir.var.decl.ast} // AFTER-NEXT: cir.func internal private @__cxx_global_var_init.1() @@ -61,11 +61,11 @@ static Init __ioinit2(false); // AFTER-NEXT: %1 = cir.const #false // AFTER-NEXT: cir.call @_ZN4InitC1Eb(%0, %1) : (!cir.ptr, !cir.bool) -> () // AFTER-NEXT: %2 = cir.get_global @_ZL9__ioinit2 : !cir.ptr -// AFTER-NEXT: %3 = cir.get_global @_ZN4InitD1Ev : !cir.ptr)>> -// AFTER-NEXT: %4 = cir.cast(bitcast, %3 : !cir.ptr)>>), !cir.ptr)>> +// AFTER-NEXT: %3 = cir.get_global @_ZN4InitD1Ev : !cir.ptr)>> +// AFTER-NEXT: %4 = cir.cast(bitcast, %3 : !cir.ptr)>>), !cir.ptr)>> // AFTER-NEXT: %5 = cir.cast(bitcast, %2 : !cir.ptr), !cir.ptr // AFTER-NEXT: %6 = cir.get_global @__dso_handle : !cir.ptr -// AFTER-NEXT: cir.call @__cxa_atexit(%4, %5, %6) : (!cir.ptr)>>, !cir.ptr, !cir.ptr) -> () +// AFTER-NEXT: cir.call @__cxa_atexit(%4, %5, %6) : (!cir.ptr)>>, !cir.ptr, !cir.ptr) -> () // AFTER-NEXT: cir.return // AFTER: cir.func private @_GLOBAL__sub_I_static.cpp() // AFTER-NEXT: cir.call @__cxx_global_var_init() : () -> () diff --git a/clang/test/CIR/IR/being_and_nothingness.cir b/clang/test/CIR/IR/being_and_nothingness.cir new file mode 100644 index 000000000000..076c75a5b192 --- /dev/null +++ b/clang/test/CIR/IR/being_and_nothingness.cir @@ -0,0 +1,28 @@ +// RUN: cir-opt %s | FileCheck %s +// Exercise different ways to encode a function returning void +!s32i = !cir.int +!f = !cir.func<()> +!f2 = !cir.func +!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) { + cir.return + } + cir.func @f2() { + // 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 + } +}