diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 493ec845b448..704ab73c9558 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1145,9 +1145,26 @@ RValue CIRGenFunction::buildCall(clang::QualType CalleeType, if (isa(FnType) || Chain) { assert(!UnimplementedFeature::chainCalls()); assert(!UnimplementedFeature::addressSpace()); + auto CalleeTy = getTypes().GetFunctionType(FnInfo); + // get non-variadic function type + CalleeTy = mlir::cir::FuncType::get(CalleeTy.getInputs(), + CalleeTy.getReturnType(), false); + auto CalleePtrTy = + mlir::cir::PointerType::get(builder.getContext(), CalleeTy); + + auto *Fn = Callee.getFunctionPointer(); + mlir::Value Addr; + if (auto funcOp = llvm::dyn_cast(Fn)) { + Addr = builder.create( + getLoc(E->getSourceRange()), + mlir::cir::PointerType::get(builder.getContext(), + funcOp.getFunctionType()), + funcOp.getSymName()); + } else { + Addr = Fn->getResult(0); + } - // Set no-proto function as callee. - auto Fn = llvm::dyn_cast(Callee.getFunctionPointer()); + Fn = builder.createBitcast(Addr, CalleePtrTy).getDefiningOp(); Callee.setFunctionPointer(Fn); } diff --git a/clang/test/CIR/CodeGen/agg-copy.c b/clang/test/CIR/CodeGen/agg-copy.c index 9b7f982716d5..d81e29161e7a 100644 --- a/clang/test/CIR/CodeGen/agg-copy.c +++ b/clang/test/CIR/CodeGen/agg-copy.c @@ -64,9 +64,9 @@ void foo4(A* a1) { A create() { A a; return a; } // CHECK: cir.func {{.*@foo5}} -// CHECK: [[TMP0]] = cir.alloca !ty_22A22, cir.ptr , -// CHECK: [[TMP1]] = cir.alloca !ty_22A22, cir.ptr , ["tmp"] {alignment = 4 : i64} -// CHECK: [[TMP2]] = cir.call @create() : () -> !ty_22A22 +// CHECK: [[TMP0:%.*]] = cir.alloca !ty_22A22, cir.ptr , +// CHECK: [[TMP1:%.*]] = cir.alloca !ty_22A22, cir.ptr , ["tmp"] {alignment = 4 : i64} +// CHECK: [[TMP2:%.*]] = cir.call @create() : () -> !ty_22A22 // CHECK: cir.store [[TMP2]], [[TMP1]] : !ty_22A22, cir.ptr // CHECK: cir.copy [[TMP1]] to [[TMP0]] : !cir.ptr void foo5() { @@ -77,9 +77,9 @@ void foo5() { void foo6(A* a1) { A a2 = (*a1); // CHECK: cir.func {{.*@foo6}} -// CHECK: [[TMP0]] = cir.alloca !cir.ptr, cir.ptr >, ["a1", init] {alignment = 8 : i64} -// CHECK: [[TMP1]] = cir.alloca !ty_22A22, cir.ptr , ["a2", init] {alignment = 4 : i64} +// CHECK: [[TMP0:%.*]] = cir.alloca !cir.ptr, cir.ptr >, ["a1", init] {alignment = 8 : i64} +// CHECK: [[TMP1:%.*]] = cir.alloca !ty_22A22, cir.ptr , ["a2", init] {alignment = 4 : i64} // CHECK: cir.store %arg0, [[TMP0]] : !cir.ptr, cir.ptr > -// CHECK: [[TMP2]] = cir.load deref [[TMP0]] : cir.ptr >, !cir.ptr +// CHECK: [[TMP2:%.*]] = cir.load deref [[TMP0]] : cir.ptr >, !cir.ptr // CHECK: cir.copy [[TMP2]] to [[TMP1]] : !cir.ptr } \ No newline at end of file diff --git a/clang/test/CIR/CodeGen/no-proto-fun-ptr.c b/clang/test/CIR/CodeGen/no-proto-fun-ptr.c index f2eb10ab5174..5789affdf103 100644 --- a/clang/test/CIR/CodeGen/no-proto-fun-ptr.c +++ b/clang/test/CIR/CodeGen/no-proto-fun-ptr.c @@ -15,3 +15,14 @@ void check_noproto_ptr() { void empty(void) {} +void buz() { + void (*func)(); + (*func)(); +} + +// 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: cir.return diff --git a/clang/test/CIR/CodeGen/no-prototype.c b/clang/test/CIR/CodeGen/no-prototype.c index df34529711eb..fb20f8cdbcd7 100644 --- a/clang/test/CIR/CodeGen/no-prototype.c +++ b/clang/test/CIR/CodeGen/no-prototype.c @@ -35,7 +35,9 @@ int test1(int x) { int noProto2(); int test2(int x) { return noProto2(x); - // CHECK: %{{.+}} = cir.call @noProto2(%{{[0-9]+}}) : (!s32i) -> !s32i + // CHECK: [[GGO:%.*]] = cir.get_global @noProto2 : cir.ptr > + // CHECK: [[CAST:%.*]] = cir.cast(bitcast, %3 : !cir.ptr>), !cir.ptr> + // CHECK: {{.*}} = cir.call [[CAST]](%{{[0-9]+}}) : (!cir.ptr>, !s32i) -> !s32i } int noProto2(int x) { return x; } // CHECK: cir.func no_proto @noProto2(%arg0: !s32i {{.+}}) -> !s32i @@ -49,7 +51,9 @@ int noProto3(); int test3(int x) { // CHECK: cir.func @test3 return noProto3(x); - // CHECK: %{{.+}} = cir.call @noProto3(%{{[0-9]+}}) : (!s32i) -> !s32i + // 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 } @@ -64,14 +68,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: %{{.+}} = cir.call @noProto4(%{{.+}}) : (!s32i) -> !s32i + // 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 } // No-proto definition followed by an incorrect call due to lack of args. int noProto5(); int test5(int x) { return noProto5(); - // CHECK: %{{.+}} = cir.call @noProto5() : () -> !s32i + // 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 } int noProto5(int x) { return x; } // CHECK: cir.func no_proto @noProto5(%arg0: !s32i {{.+}}) -> !s32i