Skip to content

Commit

Permalink
Support dereferencing function pointer
Browse files Browse the repository at this point in the history
  • Loading branch information
Lai-YT authored and leewei05 committed May 10, 2024
1 parent d7a6061 commit 58d2801
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 9 deletions.
9 changes: 9 additions & 0 deletions src/qbe_ir_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,15 @@ void QbeIrGenerator::Visit(const UnaryExprNode& unary_expr) {
num_recorder.Record(res_num);
} break;
case UnaryOperator::kDeref: {
// Is function pointer.
if (unary_expr.operand->type->IsPtr() &&
dynamic_cast<PtrType*>((unary_expr.operand->type).get())
->base_type()
.IsFunc()) {
// No-op; the function itself also evaluates to the address.
break;
}

// Lhs can use res_num to map to the address, which reg_num currently
// holds.
const int reg_num = num_recorder.NumOfPrevExpr();
Expand Down
6 changes: 3 additions & 3 deletions src/type_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,11 @@ void TypeChecker::Visit(FuncCallExprNode& call_expr) {
if (call_expr.func_expr->type->IsFunc()) {
func_type = std::dynamic_pointer_cast<FuncType>(
std::shared_ptr<Type>{call_expr.func_expr->type->Clone()});
// In case that the expression is a function type, it should be an
// identifier expression of a declared identifier (function).
const auto* id_expr =
dynamic_cast<IdExprNode*>((call_expr.func_expr).get());
if (!id_expr || !env_.LookUp(id_expr->id)) {
// If is an identifier, either a function or a function pointer, it should
// be declared.
if (id_expr && !env_.LookUp(id_expr->id)) {
// TODO: use of undeclared identifier 'id'
assert(false);
}
Expand Down
2 changes: 1 addition & 1 deletion test/codegen/func_pointer.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ int main() {
// Taking address of a function has the same effect as using the function
// name.
p = &add;
int d = p(1, 2);
int d = (*p)(1, 2);
__builtin_print(d);
return 0;
}
2 changes: 1 addition & 1 deletion test/typecheck/func_pointer.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ int main() {
p = add;
int c = p(2, 3);
p = &add;
int d = p(1, 2);
int d = (*p)(1, 2);
return 0;
}
9 changes: 5 additions & 4 deletions test/typecheck/func_pointer.exp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ ProgramNode <1:1>
IdExprNode <9:8> add: int (int, int)
DeclVarNode <10:7> d: int
FuncCallExprNode <10:11> int
IdExprNode <10:11> p: int (*)(int, int)
ArgExprNode <10:13> int
IntConstExprNode <10:13> 1: int
UnaryExprNode <10:12> int (int, int) *
IdExprNode <10:13> p: int (*)(int, int)
ArgExprNode <10:16> int
IntConstExprNode <10:16> 2: int
IntConstExprNode <10:16> 1: int
ArgExprNode <10:19> int
IntConstExprNode <10:19> 2: int
ReturnStmtNode <11:3>
IntConstExprNode <11:10> 0: int

0 comments on commit 58d2801

Please sign in to comment.