authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 20:15:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 20:15:47-07:00
log954afe5d9a5ae634f7db22641ebac6e755cdaba7
tree21183728874263dd440cb46dcb563b418f3cefbe
parentf20d0665bb9bfc3079028df59b754b028e8b83ec

fix C interaction with maybe function pointers

See #88

3 files changed, 57 insertions(+), 7 deletions(-)

src/analyze.cpp+6-2
......@@ -214,9 +214,12 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
214214 buf_resize(&entry->name, 0);
215215 buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
216216
217 if (child_type->id == TypeTableEntryIdPointer) {
217 if (child_type->id == TypeTableEntryIdPointer ||
218 child_type->id == TypeTableEntryIdFn)
219 {
218220 // this is an optimization but also is necessary for calling C
219221 // functions where all pointers are maybe pointers
222 // function types are technically pointers
220223 entry->size_in_bits = child_type->size_in_bits;
221224 entry->align_in_bits = child_type->align_in_bits;
222225 entry->type_ref = child_type->type_ref;
......@@ -5384,7 +5387,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
53845387 case TypeTableEntryIdEnum:
53855388 return type_entry->data.enumeration.gen_field_count != 0;
53865389 case TypeTableEntryIdMaybe:
5387 return type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer;
5390 return type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
5391 type_entry->data.maybe.child_type->id != TypeTableEntryIdFn;
53885392 case TypeTableEntryIdTypeDecl:
53895393 return handle_is_ptr(type_entry->data.type_decl.canonical_type);
53905394 }
src/codegen.cpp+15-5
......@@ -398,7 +398,9 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
398398
399399 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
400400
401 if (child_type->id == TypeTableEntryIdPointer) {
401 if (child_type->id == TypeTableEntryIdPointer ||
402 child_type->id == TypeTableEntryIdFn)
403 {
402404 return expr_val;
403405 } else {
404406 add_debug_source_node(g, node);
......@@ -1274,7 +1276,9 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may
12741276 TypeTableEntry *type_entry = get_expr_type(node);
12751277 assert(type_entry->id == TypeTableEntryIdMaybe);
12761278 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1277 if (child_type->id == TypeTableEntryIdPointer) {
1279 if (child_type->id == TypeTableEntryIdPointer ||
1280 child_type->id == TypeTableEntryIdFn)
1281 {
12781282 return maybe_struct_ref;
12791283 } else {
12801284 add_debug_source_node(g, node);
......@@ -1301,7 +1305,9 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
13011305 TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
13021306
13031307 LLVMValueRef cond_value;
1304 if (child_type->id == TypeTableEntryIdPointer) {
1308 if (child_type->id == TypeTableEntryIdPointer ||
1309 child_type->id == TypeTableEntryIdFn)
1310 {
13051311 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
13061312 LLVMConstNull(child_type->type_ref), "");
13071313 } else {
......@@ -1651,7 +1657,9 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
16511657 assert(expr_type->id == TypeTableEntryIdMaybe);
16521658 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
16531659 LLVMValueRef cond_value;
1654 if (child_type->id == TypeTableEntryIdPointer) {
1660 if (child_type->id == TypeTableEntryIdPointer ||
1661 child_type->id == TypeTableEntryIdFn)
1662 {
16551663 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
16561664 } else {
16571665 add_debug_source_node(g, node);
......@@ -2377,7 +2385,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
23772385 case TypeTableEntryIdMaybe:
23782386 {
23792387 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
2380 if (child_type->id == TypeTableEntryIdPointer) {
2388 if (child_type->id == TypeTableEntryIdPointer ||
2389 child_type->id == TypeTableEntryIdFn)
2390 {
23812391 if (const_val->data.x_maybe) {
23822392 return gen_const_val(g, child_type, const_val->data.x_maybe);
23832393 } else {
test/run_tests.cpp+36
......@@ -1447,6 +1447,42 @@ pub fn main(args: [][]u8) -> %void {
14471447 f(false);
14481448}
14491449 )SOURCE", "a\nb\n");
1450
1451
1452 add_simple_case("expose function pointer to C land", R"SOURCE(
1453#link("c")
1454export executable "test";
1455
1456c_import {
1457 @c_include("stdlib.h");
1458}
1459
1460export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
1461 const a_int = (&i32)(a ?? unreachable{});
1462 const b_int = (&i32)(b ?? unreachable{});
1463 if (*a_int < *b_int) {
1464 -1
1465 } else if (*a_int > *b_int) {
1466 1
1467 } else {
1468 0
1469 }
1470}
1471
1472export fn main(args: c_int, argv: &&u8) -> c_int {
1473 var array = []i32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
1474
1475 qsort((&c_void)(array.ptr), c_ulong(array.len), @sizeof(i32), compare_fn);
1476
1477 for (item, array, i) {
1478 if (item != i) {
1479 abort();
1480 }
1481 }
1482
1483 return 0;
1484}
1485 )SOURCE", "");
14501486}
14511487
14521488