Skip to content

Commit

Permalink
[CIR][CodeGen][Bugfix] store fptr of a function with no args (llvm#622)
Browse files Browse the repository at this point in the history
This PR fixes the next bug showed in the example below:
```
typedef int (*fn_t)();
int get42() { return 42; }

void foo() {
  fn_t f = get42;
}
```

The function type `fn_t` is generated as the variadic one due to no arg
types listed, this is the `codegen` feature. And once we store the
function pointer to a real function - a pointer to `get42` here has the
expected `i32 ()*` type - we get a verification error, so `bitcast` is
needed. The original `codegen` doesn't have it because of opaque
pointers used, and had the `bitcast` earlier, long time ago:
```
%f = alloca i32 (...)*
store i32 (...)* bitcast (i32 ()* @GET42 to i32 (...)*), i32 (...)** %f
```
  • Loading branch information
gitoleg authored and smeenai committed Oct 9, 2024
1 parent 457319a commit 36aacb1
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
14 changes: 12 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,10 +789,20 @@ static LValue buildFunctionDeclLValue(CIRGenFunction &CGF, const Expr *E,
auto loc = CGF.getLoc(E->getSourceRange());
CharUnits align = CGF.getContext().getDeclAlign(FD);

auto fnTy = funcOp.getFunctionType();
mlir::Type fnTy = funcOp.getFunctionType();
auto ptrTy = mlir::cir::PointerType::get(CGF.getBuilder().getContext(), fnTy);
auto addr = CGF.getBuilder().create<mlir::cir::GetGlobalOp>(
mlir::Value addr = CGF.getBuilder().create<mlir::cir::GetGlobalOp>(
loc, ptrTy, funcOp.getSymName());

if (funcOp.getFunctionType() !=
CGF.CGM.getTypes().ConvertType(FD->getType())) {
fnTy = CGF.CGM.getTypes().ConvertType(FD->getType());
ptrTy = mlir::cir::PointerType::get(CGF.getBuilder().getContext(), fnTy);

addr = CGF.getBuilder().create<mlir::cir::CastOp>(
addr.getLoc(), ptrTy, mlir::cir::CastKind::bitcast, addr);
}

return CGF.makeAddrLValue(Address(addr, fnTy, align), E->getType(),
AlignmentSource::Decl);
}
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CIR/CodeGen/store.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,17 @@ void foo(void) {
// CHECK-NEXT: cir.store %2, %0 : !s32i, !cir.ptr<!s32i>
// CHECK-NEXT: cir.return
// CHECK-NEXT: }

typedef int (*fn_t)();
int get42() { return 42; }

void storeNoArgsFn() {
fn_t f = get42;
}

// CHECK: cir.func {{.*@storeNoArgsFn}}
// CHECK: %0 = cir.alloca
// CHECK: %1 = cir.get_global @get42 : !cir.ptr<!cir.func<!s32i ()>>
// CHECK: %2 = cir.cast(bitcast, %1 : !cir.ptr<!cir.func<!s32i ()>>), !cir.ptr<!cir.func<!s32i (...)>>
// CHECK: cir.store %2, %0 : !cir.ptr<!cir.func<!s32i (...)>>, !cir.ptr<!cir.ptr<!cir.func<!s32i (...)>>>

0 comments on commit 36aacb1

Please sign in to comment.