| ... | @@ -135,10 +135,8 @@ static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) | ... | @@ -135,10 +135,8 @@ static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) |
| 135 | return g->num_lit_types[get_number_literal_kind_unsigned(x)]; | 135 | return g->num_lit_types[get_number_literal_kind_unsigned(x)]; |
| 136 | } | 136 | } |
| 137 | | 137 | |
| 138 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | 138 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_restrict) { |
| 139 | TypeTableEntry **parent_pointer = is_const ? | 139 | TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_restrict ? 1 : 0)]; |
| 140 | &child_type->pointer_const_parent : | | |
| 141 | &child_type->pointer_mut_parent; | | |
| 142 | if (*parent_pointer) { | 140 | if (*parent_pointer) { |
| 143 | return *parent_pointer; | 141 | return *parent_pointer; |
| 144 | } else { | 142 | } else { |
| ... | @@ -153,6 +151,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool | ... | @@ -153,6 +151,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 153 | entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name)); | 151 | entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name)); |
| 154 | entry->data.pointer.child_type = child_type; | 152 | entry->data.pointer.child_type = child_type; |
| 155 | entry->data.pointer.is_const = is_const; | 153 | entry->data.pointer.is_const = is_const; |
| | 154 | entry->data.pointer.is_restrict = is_restrict; |
| 156 | | 155 | |
| 157 | *parent_pointer = entry; | 156 | *parent_pointer = entry; |
| 158 | return entry; | 157 | return entry; |
| ... | @@ -241,11 +240,9 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, | ... | @@ -241,11 +240,9 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, |
| 241 | } | 240 | } |
| 242 | | 241 | |
| 243 | static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import, | 242 | static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import, |
| 244 | TypeTableEntry *child_type, bool is_const) | 243 | TypeTableEntry *child_type, bool is_const, bool is_restrict) |
| 245 | { | 244 | { |
| 246 | TypeTableEntry **parent_pointer = is_const ? | 245 | TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)][(is_restrict ? 1 : 0)]; |
| 247 | &child_type->unknown_size_array_const_parent : | | |
| 248 | &child_type->unknown_size_array_mut_parent; | | |
| 249 | if (*parent_pointer) { | 246 | if (*parent_pointer) { |
| 250 | return *parent_pointer; | 247 | return *parent_pointer; |
| 251 | } else { | 248 | } else { |
| ... | @@ -255,7 +252,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry | ... | @@ -255,7 +252,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry |
| 255 | buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name)); | 252 | buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name)); |
| 256 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); | 253 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); |
| 257 | | 254 | |
| 258 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const); | 255 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const, is_restrict); |
| 259 | | 256 | |
| 260 | unsigned element_count = 2; | 257 | unsigned element_count = 2; |
| 261 | LLVMTypeRef element_types[] = { | 258 | LLVMTypeRef element_types[] = { |
| ... | @@ -430,7 +427,9 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, | ... | @@ -430,7 +427,9 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 430 | } | 427 | } |
| 431 | } | 428 | } |
| 432 | | 429 | |
| 433 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) { | 430 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, |
| | 431 | BlockContext *context, bool restrict_allowed) |
| | 432 | { |
| 434 | assert(node->type == NodeTypeType); | 433 | assert(node->type == NodeTypeType); |
| 435 | alloc_codegen_node(node); | 434 | alloc_codegen_node(node); |
| 436 | TypeNode *type_node = &node->codegen_node->data.type_node; | 435 | TypeNode *type_node = &node->codegen_node->data.type_node; |
| ... | @@ -450,21 +449,47 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -450,21 +449,47 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 450 | } | 449 | } |
| 451 | case AstNodeTypeTypePointer: | 450 | case AstNodeTypeTypePointer: |
| 452 | { | 451 | { |
| 453 | resolve_type(g, node->data.type.child_type, import, context); | 452 | bool use_restrict = false; |
| | 453 | if (node->data.type.is_restrict) { |
| | 454 | if (!restrict_allowed) { |
| | 455 | add_node_error(g, node, |
| | 456 | buf_create_from_str("invalid restrict qualifier")); |
| | 457 | } else { |
| | 458 | use_restrict = true; |
| | 459 | } |
| | 460 | } |
| | 461 | |
| | 462 | resolve_type(g, node->data.type.child_type, import, context, false); |
| 454 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 463 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 455 | assert(child_type); | 464 | assert(child_type); |
| 456 | if (child_type->id == TypeTableEntryIdUnreachable) { | 465 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 457 | add_node_error(g, node, | 466 | add_node_error(g, node, |
| 458 | buf_create_from_str("pointer to unreachable not allowed")); | 467 | buf_create_from_str("pointer to unreachable not allowed")); |
| | 468 | type_node->entry = g->builtin_types.entry_invalid; |
| | 469 | return type_node->entry; |
| 459 | } else if (child_type->id == TypeTableEntryIdInvalid) { | 470 | } else if (child_type->id == TypeTableEntryIdInvalid) { |
| | 471 | type_node->entry = child_type; |
| 460 | return child_type; | 472 | return child_type; |
| | 473 | } else { |
| | 474 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_restrict); |
| | 475 | return type_node->entry; |
| 461 | } | 476 | } |
| 462 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const); | | |
| 463 | return type_node->entry; | | |
| 464 | } | 477 | } |
| 465 | case AstNodeTypeTypeArray: | 478 | case AstNodeTypeTypeArray: |
| 466 | { | 479 | { |
| 467 | TypeTableEntry *child_type = resolve_type(g, node->data.type.child_type, import, context); | 480 | AstNode *size_node = node->data.type.array_size; |
| | 481 | |
| | 482 | bool use_restrict = false; |
| | 483 | if (node->data.type.is_restrict) { |
| | 484 | if (!restrict_allowed || size_node) { |
| | 485 | add_node_error(g, node, |
| | 486 | buf_create_from_str("invalid restrict qualifier")); |
| | 487 | } else { |
| | 488 | use_restrict = true; |
| | 489 | } |
| | 490 | } |
| | 491 | |
| | 492 | TypeTableEntry *child_type = resolve_type(g, node->data.type.child_type, import, context, false); |
| 468 | if (child_type->id == TypeTableEntryIdUnreachable) { | 493 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 469 | add_node_error(g, node, | 494 | add_node_error(g, node, |
| 470 | buf_create_from_str("array of unreachable not allowed")); | 495 | buf_create_from_str("array of unreachable not allowed")); |
| ... | @@ -472,8 +497,6 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -472,8 +497,6 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 472 | return type_node->entry; | 497 | return type_node->entry; |
| 473 | } | 498 | } |
| 474 | | 499 | |
| 475 | AstNode *size_node = node->data.type.array_size; | | |
| 476 | | | |
| 477 | if (size_node) { | 500 | if (size_node) { |
| 478 | TypeTableEntry *size_type = analyze_expression(g, import, context, | 501 | TypeTableEntry *size_type = analyze_expression(g, import, context, |
| 479 | g->builtin_types.entry_usize, size_node); | 502 | g->builtin_types.entry_usize, size_node); |
| ... | @@ -501,14 +524,14 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -501,14 +524,14 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 501 | return type_node->entry; | 524 | return type_node->entry; |
| 502 | } else { | 525 | } else { |
| 503 | type_node->entry = get_unknown_size_array_type(g, import, child_type, | 526 | type_node->entry = get_unknown_size_array_type(g, import, child_type, |
| 504 | node->data.type.is_const); | 527 | node->data.type.is_const, use_restrict); |
| 505 | return type_node->entry; | 528 | return type_node->entry; |
| 506 | } | 529 | } |
| 507 | | 530 | |
| 508 | } | 531 | } |
| 509 | case AstNodeTypeTypeMaybe: | 532 | case AstNodeTypeTypeMaybe: |
| 510 | { | 533 | { |
| 511 | resolve_type(g, node->data.type.child_type, import, context); | 534 | resolve_type(g, node->data.type.child_type, import, context, false); |
| 512 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 535 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 513 | assert(child_type); | 536 | assert(child_type); |
| 514 | if (child_type->id == TypeTableEntryIdUnreachable) { | 537 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| ... | @@ -571,7 +594,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t | ... | @@ -571,7 +594,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 571 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { | 594 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 572 | AstNode *child = node->data.fn_proto.params.at(i); | 595 | AstNode *child = node->data.fn_proto.params.at(i); |
| 573 | assert(child->type == NodeTypeParamDecl); | 596 | assert(child->type == NodeTypeParamDecl); |
| 574 | TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type, import, import->block_context); | 597 | TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type, |
| | 598 | import, import->block_context, true); |
| 575 | if (type_entry->id == TypeTableEntryIdUnreachable) { | 599 | if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 576 | add_node_error(g, child->data.param_decl.type, | 600 | add_node_error(g, child->data.param_decl.type, |
| 577 | buf_sprintf("parameter of type 'unreachable' not allowed")); | 601 | buf_sprintf("parameter of type 'unreachable' not allowed")); |
| ... | @@ -583,7 +607,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t | ... | @@ -583,7 +607,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 583 | } | 607 | } |
| 584 | } | 608 | } |
| 585 | | 609 | |
| 586 | resolve_type(g, node->data.fn_proto.return_type, import, import->block_context); | 610 | resolve_type(g, node->data.fn_proto.return_type, import, import->block_context, true); |
| 587 | } | 611 | } |
| 588 | | 612 | |
| 589 | static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { | 613 | static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { |
| ... | @@ -644,7 +668,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE | ... | @@ -644,7 +668,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 644 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); | 668 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 645 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 669 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 646 | type_struct_field->name = &field_node->data.struct_field.name; | 670 | type_struct_field->name = &field_node->data.struct_field.name; |
| 647 | type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type, import, import->block_context); | 671 | type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type, |
| | 672 | import, import->block_context, false); |
| 648 | | 673 | |
| 649 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { | 674 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { |
| 650 | resolve_struct_type(g, import, type_struct_field->type_entry); | 675 | resolve_struct_type(g, import, type_struct_field->type_entry); |
| ... | @@ -1196,15 +1221,18 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont | ... | @@ -1196,15 +1221,18 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1196 | return expected_type; | 1221 | return expected_type; |
| 1197 | } | 1222 | } |
| 1198 | | 1223 | |
| 1199 | // implicit non-const to const | 1224 | // implicit non-const to const and ignore restrict |
| 1200 | if (expected_type->id == TypeTableEntryIdPointer && | 1225 | if (expected_type->id == TypeTableEntryIdPointer && |
| 1201 | actual_type->id == TypeTableEntryIdPointer && | 1226 | actual_type->id == TypeTableEntryIdPointer && |
| 1202 | expected_type->data.pointer.is_const && | 1227 | (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const)) |
| 1203 | !actual_type->data.pointer.is_const) | | |
| 1204 | { | 1228 | { |
| 1205 | return resolve_type_compatibility(g, context, node, | 1229 | TypeTableEntry *resolved_type = resolve_type_compatibility(g, context, node, |
| 1206 | expected_type->data.pointer.child_type, | 1230 | expected_type->data.pointer.child_type, |
| 1207 | actual_type->data.pointer.child_type); | 1231 | actual_type->data.pointer.child_type); |
| | 1232 | if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 1233 | return resolved_type; |
| | 1234 | } |
| | 1235 | return expected_type; |
| 1208 | } | 1236 | } |
| 1209 | | 1237 | |
| 1210 | add_node_error(g, first_executing_node(node), | 1238 | add_node_error(g, first_executing_node(node), |
| ... | @@ -1335,7 +1363,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1335,7 +1363,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 1335 | return_type = g->builtin_types.entry_usize; | 1363 | return_type = g->builtin_types.entry_usize; |
| 1336 | } else if (buf_eql_str(name, "ptr")) { | 1364 | } else if (buf_eql_str(name, "ptr")) { |
| 1337 | // TODO determine whether the pointer should be const | 1365 | // TODO determine whether the pointer should be const |
| 1338 | return_type = get_pointer_to_type(g, struct_type->data.array.child_type, false); | 1366 | return_type = get_pointer_to_type(g, struct_type->data.array.child_type, false, false); |
| 1339 | } else { | 1367 | } else { |
| 1340 | add_node_error(g, node, | 1368 | add_node_error(g, node, |
| 1341 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(name), | 1369 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(name), |
| ... | @@ -1365,16 +1393,16 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1365,16 +1393,16 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, |
| 1365 | return_type = g->builtin_types.entry_invalid; | 1393 | return_type = g->builtin_types.entry_invalid; |
| 1366 | } else if (array_type->id == TypeTableEntryIdArray) { | 1394 | } else if (array_type->id == TypeTableEntryIdArray) { |
| 1367 | return_type = get_unknown_size_array_type(g, import, array_type->data.array.child_type, | 1395 | return_type = get_unknown_size_array_type(g, import, array_type->data.array.child_type, |
| 1368 | node->data.slice_expr.is_const); | 1396 | node->data.slice_expr.is_const, false); |
| 1369 | } else if (array_type->id == TypeTableEntryIdPointer) { | 1397 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 1370 | return_type = get_unknown_size_array_type(g, import, array_type->data.pointer.child_type, | 1398 | return_type = get_unknown_size_array_type(g, import, array_type->data.pointer.child_type, |
| 1371 | node->data.slice_expr.is_const); | 1399 | node->data.slice_expr.is_const, false); |
| 1372 | } else if (array_type->id == TypeTableEntryIdStruct && | 1400 | } else if (array_type->id == TypeTableEntryIdStruct && |
| 1373 | array_type->data.structure.is_unknown_size_array) | 1401 | array_type->data.structure.is_unknown_size_array) |
| 1374 | { | 1402 | { |
| 1375 | return_type = get_unknown_size_array_type(g, import, | 1403 | return_type = get_unknown_size_array_type(g, import, |
| 1376 | array_type->data.structure.fields[0].type_entry->data.pointer.child_type, | 1404 | array_type->data.structure.fields[0].type_entry->data.pointer.child_type, |
| 1377 | node->data.slice_expr.is_const); | 1405 | node->data.slice_expr.is_const, false); |
| 1378 | } else { | 1406 | } else { |
| 1379 | add_node_error(g, node, | 1407 | add_node_error(g, node, |
| 1380 | buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name))); | 1408 | buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name))); |
| ... | @@ -1490,7 +1518,7 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { | ... | @@ -1490,7 +1518,7 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 1490 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1518 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1491 | TypeTableEntry *expected_type, AstNode *node) | 1519 | TypeTableEntry *expected_type, AstNode *node) |
| 1492 | { | 1520 | { |
| 1493 | TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context); | 1521 | TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context, false); |
| 1494 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); | 1522 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); |
| 1495 | | 1523 | |
| 1496 | if (wanted_type->id == TypeTableEntryIdInvalid || | 1524 | if (wanted_type->id == TypeTableEntryIdInvalid || |
| ... | @@ -1713,7 +1741,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa | ... | @@ -1713,7 +1741,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 1713 | { | 1741 | { |
| 1714 | TypeTableEntry *explicit_type = nullptr; | 1742 | TypeTableEntry *explicit_type = nullptr; |
| 1715 | if (variable_declaration->type != nullptr) { | 1743 | if (variable_declaration->type != nullptr) { |
| 1716 | explicit_type = resolve_type(g, variable_declaration->type, import, context); | 1744 | explicit_type = resolve_type(g, variable_declaration->type, import, context, false); |
| 1717 | if (explicit_type->id == TypeTableEntryIdUnreachable) { | 1745 | if (explicit_type->id == TypeTableEntryIdUnreachable) { |
| 1718 | add_node_error(g, variable_declaration->type, | 1746 | add_node_error(g, variable_declaration->type, |
| 1719 | buf_sprintf("variable of type 'unreachable' not allowed")); | 1747 | buf_sprintf("variable of type 'unreachable' not allowed")); |
| ... | @@ -1837,7 +1865,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -1837,7 +1865,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1837 | | 1865 | |
| 1838 | AstNodeStructValueExpr *struct_val_expr = &node->data.struct_val_expr; | 1866 | AstNodeStructValueExpr *struct_val_expr = &node->data.struct_val_expr; |
| 1839 | | 1867 | |
| 1840 | TypeTableEntry *type_entry = resolve_type(g, struct_val_expr->type, import, context); | 1868 | TypeTableEntry *type_entry = resolve_type(g, struct_val_expr->type, import, context, false); |
| 1841 | | 1869 | |
| 1842 | if (type_entry->id == TypeTableEntryIdInvalid) { | 1870 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 1843 | return g->builtin_types.entry_invalid; | 1871 | return g->builtin_types.entry_invalid; |
| ... | @@ -2017,7 +2045,7 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im | ... | @@ -2017,7 +2045,7 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im |
| 2017 | assert(node->type == NodeTypeCompilerFnType); | 2045 | assert(node->type == NodeTypeCompilerFnType); |
| 2018 | | 2046 | |
| 2019 | Buf *name = &node->data.compiler_fn_type.name; | 2047 | Buf *name = &node->data.compiler_fn_type.name; |
| 2020 | TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context); | 2048 | TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context, false); |
| 2021 | | 2049 | |
| 2022 | if (buf_eql_str(name, "sizeof")) { | 2050 | if (buf_eql_str(name, "sizeof")) { |
| 2023 | uint64_t size_in_bytes = type_entry->size_in_bits / 8; | 2051 | uint64_t size_in_bytes = type_entry->size_in_bits / 8; |
| ... | @@ -2221,7 +2249,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2221,7 +2249,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2221 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); | 2249 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); |
| 2222 | if (asm_output->return_type) { | 2250 | if (asm_output->return_type) { |
| 2223 | node->data.asm_expr.return_count += 1; | 2251 | node->data.asm_expr.return_count += 1; |
| 2224 | return_type = resolve_type(g, asm_output->return_type, import, context); | 2252 | return_type = resolve_type(g, asm_output->return_type, import, context, false); |
| 2225 | if (node->data.asm_expr.return_count > 1) { | 2253 | if (node->data.asm_expr.return_count > 1) { |
| 2226 | add_node_error(g, node, | 2254 | add_node_error(g, node, |
| 2227 | buf_sprintf("inline assembly allows up to one output value")); | 2255 | buf_sprintf("inline assembly allows up to one output value")); |
| ... | @@ -2357,7 +2385,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2357,7 +2385,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2357 | break; | 2385 | break; |
| 2358 | } | 2386 | } |
| 2359 | | 2387 | |
| 2360 | return_type = get_pointer_to_type(g, child_type, is_const); | 2388 | return_type = get_pointer_to_type(g, child_type, is_const, false); |
| 2361 | break; | 2389 | break; |
| 2362 | } | 2390 | } |
| 2363 | case PrefixOpDereference: | 2391 | case PrefixOpDereference: |