| author | |
| committer | |
| log | 954afe5d9a5ae634f7db22641ebac6e755cdaba7 |
| tree | 21183728874263dd440cb46dcb563b418f3cefbe |
| parent | f20d0665bb9bfc3079028df59b754b028e8b83ec |
See #883 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 | 214 | buf_resize(&entry->name, 0); |
| 215 | 215 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); |
| 216 | 216 | |
| 217 | if (child_type->id == TypeTableEntryIdPointer) { | |
| 217 | if (child_type->id == TypeTableEntryIdPointer || | |
| 218 | child_type->id == TypeTableEntryIdFn) | |
| 219 | { | |
| 218 | 220 | // this is an optimization but also is necessary for calling C |
| 219 | 221 | // functions where all pointers are maybe pointers |
| 222 | // function types are technically pointers | |
| 220 | 223 | entry->size_in_bits = child_type->size_in_bits; |
| 221 | 224 | entry->align_in_bits = child_type->align_in_bits; |
| 222 | 225 | entry->type_ref = child_type->type_ref; |
| ... | ... | @@ -5384,7 +5387,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 5384 | 5387 | case TypeTableEntryIdEnum: |
| 5385 | 5388 | return type_entry->data.enumeration.gen_field_count != 0; |
| 5386 | 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 | 5392 | case TypeTableEntryIdTypeDecl: |
| 5389 | 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 | 398 | |
| 399 | 399 | TypeTableEntry *child_type = wanted_type->data.maybe.child_type; |
| 400 | 400 | |
| 401 | if (child_type->id == TypeTableEntryIdPointer) { | |
| 401 | if (child_type->id == TypeTableEntryIdPointer || | |
| 402 | child_type->id == TypeTableEntryIdFn) | |
| 403 | { | |
| 402 | 404 | return expr_val; |
| 403 | 405 | } else { |
| 404 | 406 | add_debug_source_node(g, node); |
| ... | ... | @@ -1274,7 +1276,9 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may |
| 1274 | 1276 | TypeTableEntry *type_entry = get_expr_type(node); |
| 1275 | 1277 | assert(type_entry->id == TypeTableEntryIdMaybe); |
| 1276 | 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 | 1282 | return maybe_struct_ref; |
| 1279 | 1283 | } else { |
| 1280 | 1284 | add_debug_source_node(g, node); |
| ... | ... | @@ -1301,7 +1305,9 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) { |
| 1301 | 1305 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 1302 | 1306 | |
| 1303 | 1307 | LLVMValueRef cond_value; |
| 1304 | if (child_type->id == TypeTableEntryIdPointer) { | |
| 1308 | if (child_type->id == TypeTableEntryIdPointer || | |
| 1309 | child_type->id == TypeTableEntryIdFn) | |
| 1310 | { | |
| 1305 | 1311 | cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref, |
| 1306 | 1312 | LLVMConstNull(child_type->type_ref), ""); |
| 1307 | 1313 | } else { |
| ... | ... | @@ -1651,7 +1657,9 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 1651 | 1657 | assert(expr_type->id == TypeTableEntryIdMaybe); |
| 1652 | 1658 | TypeTableEntry *child_type = expr_type->data.maybe.child_type; |
| 1653 | 1659 | LLVMValueRef cond_value; |
| 1654 | if (child_type->id == TypeTableEntryIdPointer) { | |
| 1660 | if (child_type->id == TypeTableEntryIdPointer || | |
| 1661 | child_type->id == TypeTableEntryIdFn) | |
| 1662 | { | |
| 1655 | 1663 | cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), ""); |
| 1656 | 1664 | } else { |
| 1657 | 1665 | add_debug_source_node(g, node); |
| ... | ... | @@ -2377,7 +2385,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE |
| 2377 | 2385 | case TypeTableEntryIdMaybe: |
| 2378 | 2386 | { |
| 2379 | 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 | 2391 | if (const_val->data.x_maybe) { |
| 2382 | 2392 | return gen_const_val(g, child_type, const_val->data.x_maybe); |
| 2383 | 2393 | } else { |
test/run_tests.cpp+36| ... | ... | @@ -1447,6 +1447,42 @@ pub fn main(args: [][]u8) -> %void { |
| 1447 | 1447 | f(false); |
| 1448 | 1448 | } |
| 1449 | 1449 | )SOURCE", "a\nb\n"); |
| 1450 | ||
| 1451 | ||
| 1452 | add_simple_case("expose function pointer to C land", R"SOURCE( | |
| 1453 | #link("c") | |
| 1454 | export executable "test"; | |
| 1455 | ||
| 1456 | c_import { | |
| 1457 | @c_include("stdlib.h"); | |
| 1458 | } | |
| 1459 | ||
| 1460 | export 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 | ||
| 1472 | export 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 | } |
| 1451 | 1487 | |
| 1452 | 1488 |