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) {...@@ -214,9 +214,12 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
214 buf_resize(&entry->name, 0);214 buf_resize(&entry->name, 0);
215 buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));215 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 {
218 // this is an optimization but also is necessary for calling C220 // this is an optimization but also is necessary for calling C
219 // functions where all pointers are maybe pointers221 // functions where all pointers are maybe pointers
222 // function types are technically pointers
220 entry->size_in_bits = child_type->size_in_bits;223 entry->size_in_bits = child_type->size_in_bits;
221 entry->align_in_bits = child_type->align_in_bits;224 entry->align_in_bits = child_type->align_in_bits;
222 entry->type_ref = child_type->type_ref;225 entry->type_ref = child_type->type_ref;
...@@ -5384,7 +5387,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {...@@ -5384,7 +5387,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
5384 case TypeTableEntryIdEnum:5387 case TypeTableEntryIdEnum:
5385 return type_entry->data.enumeration.gen_field_count != 0;5388 return type_entry->data.enumeration.gen_field_count != 0;
5386 case TypeTableEntryIdMaybe:5389 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;
5388 case TypeTableEntryIdTypeDecl:5392 case TypeTableEntryIdTypeDecl:
5389 return handle_is_ptr(type_entry->data.type_decl.canonical_type);5393 return handle_is_ptr(type_entry->data.type_decl.canonical_type);
5390 }5394 }
src/codegen.cpp+15-5
...@@ -398,7 +398,9 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {...@@ -398,7 +398,9 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
398398
399 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;399 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 {
402 return expr_val;404 return expr_val;
403 } else {405 } else {
404 add_debug_source_node(g, node);406 add_debug_source_node(g, node);
...@@ -1274,7 +1276,9 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may...@@ -1274,7 +1276,9 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may
1274 TypeTableEntry *type_entry = get_expr_type(node);1276 TypeTableEntry *type_entry = get_expr_type(node);
1275 assert(type_entry->id == TypeTableEntryIdMaybe);1277 assert(type_entry->id == TypeTableEntryIdMaybe);
1276 TypeTableEntry *child_type = type_entry->data.maybe.child_type;1278 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 {
1278 return maybe_struct_ref;1282 return maybe_struct_ref;
1279 } else {1283 } else {
1280 add_debug_source_node(g, node);1284 add_debug_source_node(g, node);
...@@ -1301,7 +1305,9 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {...@@ -1301,7 +1305,9 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
1301 TypeTableEntry *child_type = maybe_type->data.maybe.child_type;1305 TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
13021306
1303 LLVMValueRef cond_value;1307 LLVMValueRef cond_value;
1304 if (child_type->id == TypeTableEntryIdPointer) {1308 if (child_type->id == TypeTableEntryIdPointer ||
1309 child_type->id == TypeTableEntryIdFn)
1310 {
1305 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,1311 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
1306 LLVMConstNull(child_type->type_ref), "");1312 LLVMConstNull(child_type->type_ref), "");
1307 } else {1313 } else {
...@@ -1651,7 +1657,9 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -1651,7 +1657,9 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
1651 assert(expr_type->id == TypeTableEntryIdMaybe);1657 assert(expr_type->id == TypeTableEntryIdMaybe);
1652 TypeTableEntry *child_type = expr_type->data.maybe.child_type;1658 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
1653 LLVMValueRef cond_value;1659 LLVMValueRef cond_value;
1654 if (child_type->id == TypeTableEntryIdPointer) {1660 if (child_type->id == TypeTableEntryIdPointer ||
1661 child_type->id == TypeTableEntryIdFn)
1662 {
1655 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");1663 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
1656 } else {1664 } else {
1657 add_debug_source_node(g, node);1665 add_debug_source_node(g, node);
...@@ -2377,7 +2385,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2377,7 +2385,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2377 case TypeTableEntryIdMaybe:2385 case TypeTableEntryIdMaybe:
2378 {2386 {
2379 TypeTableEntry *child_type = type_entry->data.maybe.child_type;2387 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 {
2381 if (const_val->data.x_maybe) {2391 if (const_val->data.x_maybe) {
2382 return gen_const_val(g, child_type, const_val->data.x_maybe);2392 return gen_const_val(g, child_type, const_val->data.x_maybe);
2383 } else {2393 } else {
test/run_tests.cpp+36
...@@ -1447,6 +1447,42 @@ pub fn main(args: [][]u8) -> %void {...@@ -1447,6 +1447,42 @@ pub fn main(args: [][]u8) -> %void {
1447 f(false);1447 f(false);
1448}1448}
1449 )SOURCE", "a\nb\n");1449 )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", "");
1450}1486}
14511487
14521488