authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-10 00:14:30-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-10 00:14:30-05:00
logb8cbe3872e702ab8ec388e75cb711330a45825b0
tree3f0162c85bee328083466f1c2d164eb4035450bb
parentcaf672c49586f1af5e3d41ae200aded991b8b0f7
signaturelock-open Commit is signed but in an unrecognized format.

added C pointer type and implicit int-to-ptr for this type

See #1059

7 files changed, 210 insertions(+), 75 deletions(-)

src/all_types.hpp+1
...@@ -1038,6 +1038,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);...@@ -1038,6 +1038,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
1038enum PtrLen {1038enum PtrLen {
1039 PtrLenUnknown,1039 PtrLenUnknown,
1040 PtrLenSingle,1040 PtrLenSingle,
1041 PtrLenC,
1041};1042};
10421043
1043struct ZigTypePointer {1044struct ZigTypePointer {
src/analyze.cpp+13-1
...@@ -417,6 +417,18 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {...@@ -417,6 +417,18 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
417 return entry;417 return entry;
418}418}
419419
420static const char *ptr_len_to_star_str(PtrLen ptr_len) {
421 switch (ptr_len) {
422 case PtrLenSingle:
423 return "*";
424 case PtrLenUnknown:
425 return "[*]";
426 case PtrLenC:
427 return "[*c]";
428 }
429 zig_unreachable();
430}
431
420ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,432ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
421 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,433 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
422 uint32_t bit_offset_in_host, uint32_t host_int_bytes)434 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
...@@ -466,7 +478,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -466,7 +478,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
466478
467 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);479 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
468480
469 const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";481 const char *star_str = ptr_len_to_star_str(ptr_len);
470 const char *const_str = is_const ? "const " : "";482 const char *const_str = is_const ? "const " : "";
471 const char *volatile_str = is_volatile ? "volatile " : "";483 const char *volatile_str = is_volatile ? "volatile " : "";
472 buf_resize(&entry->name, 0);484 buf_resize(&entry->name, 0);
src/ir.cpp+163-73
...@@ -169,6 +169,10 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -169,6 +169,10 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
172static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
173 ZigType *ptr_type);
174static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
175 ZigType *dest_type);
172176
173static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {177static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
174 assert(get_src_ptr_type(const_val->type) != nullptr);178 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -5019,10 +5023,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *...@@ -5019,10 +5023,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
5019 return ir_build_ref(irb, scope, value->source_node, value, false, false);5023 return ir_build_ref(irb, scope, value->source_node, value, false, false);
5020}5024}
50215025
5026static PtrLen star_token_to_ptr_len(TokenId token_id) {
5027 switch (token_id) {
5028 case TokenIdStar:
5029 case TokenIdStarStar:
5030 return PtrLenSingle;
5031 case TokenIdBracketStarBracket:
5032 return PtrLenUnknown;
5033 case TokenIdBracketStarCBracket:
5034 return PtrLenC;
5035 default:
5036 zig_unreachable();
5037 }
5038}
5039
5022static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {5040static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
5023 assert(node->type == NodeTypePointerType);5041 assert(node->type == NodeTypePointerType);
5024 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||5042 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
5025 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5026 bool is_const = node->data.pointer_type.is_const;5043 bool is_const = node->data.pointer_type.is_const;
5027 bool is_volatile = node->data.pointer_type.is_volatile;5044 bool is_volatile = node->data.pointer_type.is_volatile;
5028 AstNode *expr_node = node->data.pointer_type.op_expr;5045 AstNode *expr_node = node->data.pointer_type.op_expr;
...@@ -8538,6 +8555,20 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -8538,6 +8555,20 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
8538 }8555 }
8539 }8556 }
8540 }8557 }
8558 if (other_type->id == ZigTypeIdPointer && other_type->data.pointer.ptr_len == PtrLenC && const_val_is_int) {
8559 if (!bigint_fits_in_bits(&const_val->data.x_bigint, ira->codegen->pointer_size_bytes * 8, true) &&
8560 !bigint_fits_in_bits(&const_val->data.x_bigint, ira->codegen->pointer_size_bytes * 8, false))
8561 {
8562 Buf *val_buf = buf_alloc();
8563 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
8564
8565 ir_add_error(ira, instruction,
8566 buf_sprintf("integer value %s outside of pointer address range",
8567 buf_ptr(val_buf)));
8568 return false;
8569 }
8570 return true;
8571 }
85418572
8542 const char *num_lit_str;8573 const char *num_lit_str;
8543 Buf *val_buf = buf_alloc();8574 Buf *val_buf = buf_alloc();
...@@ -10811,6 +10842,37 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *...@@ -10811,6 +10842,37 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
10811 return ir_build_vector_to_array(ira, source_instr, vector, array_type);10842 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
10812}10843}
1081310844
10845static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
10846 IrInstruction *integer, ZigType *dest_type)
10847{
10848 IrInstruction *unsigned_integer;
10849 if (instr_is_comptime(integer)) {
10850 unsigned_integer = integer;
10851 } else {
10852 assert(integer->value.type->id == ZigTypeIdInt);
10853
10854 if (integer->value.type->data.integral.bit_count >
10855 ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
10856 {
10857 ir_add_error(ira, source_instr,
10858 buf_sprintf("integer type too big for implicit @intToPtr to type '%s'", buf_ptr(&dest_type->name)));
10859 return ira->codegen->invalid_instruction;
10860 }
10861
10862 if (integer->value.type->data.integral.is_signed) {
10863 ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
10864 integer->value.type->data.integral.bit_count);
10865 unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type);
10866 if (type_is_invalid(unsigned_integer->value.type))
10867 return ira->codegen->invalid_instruction;
10868 } else {
10869 unsigned_integer = integer;
10870 }
10871 }
10872
10873 return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type);
10874}
10875
10814static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,10876static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
10815 ZigType *wanted_type, IrInstruction *value)10877 ZigType *wanted_type, IrInstruction *value)
10816{10878{
...@@ -11217,6 +11279,14 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11217,6 +11279,14 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11217 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);11279 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
11218 }11280 }
1121911281
11282 // casting to C pointers
11283 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC) {
11284 // cast from integer to C pointer
11285 if (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt) {
11286 return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
11287 }
11288 }
11289
11220 // cast from undefined to anything11290 // cast from undefined to anything
11221 if (actual_type->id == ZigTypeIdUndefined) {11291 if (actual_type->id == ZigTypeIdUndefined) {
11222 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);11292 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
...@@ -20674,32 +20744,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20674,32 +20744,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20674 zig_unreachable();20744 zig_unreachable();
20675}20745}
2067620746
20677static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {20747static bool type_can_bit_cast(ZigType *t) {
20678 Error err;20748 switch (t->id) {
20679 IrInstruction *dest_type_value = instruction->dest_type->child;
20680 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20681 if (type_is_invalid(dest_type))
20682 return ira->codegen->invalid_instruction;
20683
20684 IrInstruction *value = instruction->value->child;
20685 ZigType *src_type = value->value.type;
20686 if (type_is_invalid(src_type))
20687 return ira->codegen->invalid_instruction;
20688
20689 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20690 return ira->codegen->invalid_instruction;
20691
20692 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20693 return ira->codegen->invalid_instruction;
20694
20695 if (get_codegen_ptr_type(src_type) != nullptr) {
20696 ir_add_error(ira, value,
20697 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20698 return ira->codegen->invalid_instruction;
20699 }
20700
20701 switch (src_type->id) {
20702 case ZigTypeIdInvalid:20749 case ZigTypeIdInvalid:
20750 zig_unreachable();
20703 case ZigTypeIdMetaType:20751 case ZigTypeIdMetaType:
20704 case ZigTypeIdOpaque:20752 case ZigTypeIdOpaque:
20705 case ZigTypeIdBoundFn:20753 case ZigTypeIdBoundFn:
...@@ -20710,42 +20758,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20710,42 +20758,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20710 case ZigTypeIdComptimeInt:20758 case ZigTypeIdComptimeInt:
20711 case ZigTypeIdUndefined:20759 case ZigTypeIdUndefined:
20712 case ZigTypeIdNull:20760 case ZigTypeIdNull:
20713 ir_add_error(ira, dest_type_value,20761 case ZigTypeIdPointer:
20714 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));20762 return false;
20715 return ira->codegen->invalid_instruction;
20716 default:20763 default:
20717 break;20764 // TODO list these types out explicitly, there are probably some other invalid ones here
20765 return true;
20718 }20766 }
20767}
2071920768
20720 if (get_codegen_ptr_type(dest_type) != nullptr) {20769static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20721 ir_add_error(ira, dest_type_value,20770 ZigType *dest_type)
20722 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));20771{
20772 Error err;
20773
20774 ZigType *src_type = value->value.type;
20775 assert(get_codegen_ptr_type(src_type) == nullptr);
20776 assert(type_can_bit_cast(src_type));
20777 assert(get_codegen_ptr_type(dest_type) == nullptr);
20778 assert(type_can_bit_cast(dest_type));
20779
20780 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20781 return ira->codegen->invalid_instruction;
20782
20783 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20723 return ira->codegen->invalid_instruction;20784 return ira->codegen->invalid_instruction;
20724 }
2072520785
20726 switch (dest_type->id) {
20727 case ZigTypeIdInvalid:
20728 case ZigTypeIdMetaType:
20729 case ZigTypeIdOpaque:
20730 case ZigTypeIdBoundFn:
20731 case ZigTypeIdArgTuple:
20732 case ZigTypeIdNamespace:
20733 case ZigTypeIdUnreachable:
20734 case ZigTypeIdComptimeFloat:
20735 case ZigTypeIdComptimeInt:
20736 case ZigTypeIdUndefined:
20737 case ZigTypeIdNull:
20738 ir_add_error(ira, dest_type_value,
20739 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20740 return ira->codegen->invalid_instruction;
20741 default:
20742 break;
20743 }
2074420786
20745 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);20787 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
20746 uint64_t src_size_bytes = type_size(ira->codegen, src_type);20788 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
20747 if (dest_size_bytes != src_size_bytes) {20789 if (dest_size_bytes != src_size_bytes) {
20748 ir_add_error(ira, &instruction->base,20790 ir_add_error(ira, source_instr,
20749 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,20791 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
20750 buf_ptr(&dest_type->name), dest_size_bytes,20792 buf_ptr(&dest_type->name), dest_size_bytes,
20751 buf_ptr(&src_type->name), src_size_bytes));20793 buf_ptr(&src_type->name), src_size_bytes));
...@@ -20755,7 +20797,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20755,7 +20797,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20755 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);20797 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
20756 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);20798 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
20757 if (dest_size_bits != src_size_bits) {20799 if (dest_size_bits != src_size_bits) {
20758 ir_add_error(ira, &instruction->base,20800 ir_add_error(ira, source_instr,
20759 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",20801 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
20760 buf_ptr(&dest_type->name), dest_size_bits,20802 buf_ptr(&dest_type->name), dest_size_bits,
20761 buf_ptr(&src_type->name), src_size_bits));20803 buf_ptr(&src_type->name), src_size_bits));
...@@ -20767,44 +20809,63 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20767,44 +20809,63 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20767 if (!val)20809 if (!val)
20768 return ira->codegen->invalid_instruction;20810 return ira->codegen->invalid_instruction;
2076920811
20770 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);20812 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20771 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);20813 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
20772 buf_write_value_bytes(ira->codegen, buf, val);20814 buf_write_value_bytes(ira->codegen, buf, val);
20773 if ((err = buf_read_value_bytes(ira, ira->codegen, instruction->base.source_node, buf, &result->value)))20815 if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value)))
20774 return ira->codegen->invalid_instruction;20816 return ira->codegen->invalid_instruction;
20775 return result;20817 return result;
20776 }20818 }
2077720819
20778 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,20820 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
20779 instruction->base.source_node, nullptr, value);20821 source_instr->source_node, nullptr, value);
20780 result->value.type = dest_type;20822 result->value.type = dest_type;
20781 return result;20823 return result;
20782}20824}
2078320825
20784static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {20826static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20785 Error err;
20786 IrInstruction *dest_type_value = instruction->dest_type->child;20827 IrInstruction *dest_type_value = instruction->dest_type->child;
20787 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);20828 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20788 if (type_is_invalid(dest_type))20829 if (type_is_invalid(dest_type))
20789 return ira->codegen->invalid_instruction;20830 return ira->codegen->invalid_instruction;
2079020831
20791 // We explicitly check for the size, so we can use get_src_ptr_type20832 IrInstruction *value = instruction->value->child;
20792 if (get_src_ptr_type(dest_type) == nullptr) {20833 ZigType *src_type = value->value.type;
20793 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));20834 if (type_is_invalid(src_type))
20835 return ira->codegen->invalid_instruction;
20836
20837 if (get_codegen_ptr_type(src_type) != nullptr) {
20838 ir_add_error(ira, value,
20839 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20794 return ira->codegen->invalid_instruction;20840 return ira->codegen->invalid_instruction;
20795 }20841 }
2079620842
20797 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))20843 if (!type_can_bit_cast(src_type)) {
20844 ir_add_error(ira, dest_type_value,
20845 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
20798 return ira->codegen->invalid_instruction;20846 return ira->codegen->invalid_instruction;
20799 if (!type_has_bits(dest_type)) {20847 }
20848
20849 if (get_codegen_ptr_type(dest_type) != nullptr) {
20800 ir_add_error(ira, dest_type_value,20850 ir_add_error(ira, dest_type_value,
20801 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));20851 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
20802 return ira->codegen->invalid_instruction;20852 return ira->codegen->invalid_instruction;
20803 }20853 }
2080420854
20805 IrInstruction *target = instruction->target->child;20855 if (!type_can_bit_cast(dest_type)) {
20806 if (type_is_invalid(target->value.type))20856 ir_add_error(ira, dest_type_value,
20857 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20807 return ira->codegen->invalid_instruction;20858 return ira->codegen->invalid_instruction;
20859 }
20860
20861 return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
20862}
20863
20864static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
20865 ZigType *ptr_type)
20866{
20867 assert(get_src_ptr_type(ptr_type) != nullptr);
20868 assert(type_has_bits(ptr_type));
2080820869
20809 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);20870 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
20810 if (type_is_invalid(casted_int->value.type))20871 if (type_is_invalid(casted_int->value.type))
...@@ -20815,19 +20876,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru...@@ -20815,19 +20876,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
20815 if (!val)20876 if (!val)
20816 return ira->codegen->invalid_instruction;20877 return ira->codegen->invalid_instruction;
2081720878
20818 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);20879 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
20819 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;20880 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
20820 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;20881 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
20821 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);20882 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
20822 return result;20883 return result;
20823 }20884 }
2082420885
20825 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,20886 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
20826 instruction->base.source_node, nullptr, casted_int);20887 source_instr->source_node, nullptr, casted_int);
20827 result->value.type = dest_type;20888 result->value.type = ptr_type;
20828 return result;20889 return result;
20829}20890}
2083020891
20892static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
20893 Error err;
20894 IrInstruction *dest_type_value = instruction->dest_type->child;
20895 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20896 if (type_is_invalid(dest_type))
20897 return ira->codegen->invalid_instruction;
20898
20899 // We explicitly check for the size, so we can use get_src_ptr_type
20900 if (get_src_ptr_type(dest_type) == nullptr) {
20901 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
20902 return ira->codegen->invalid_instruction;
20903 }
20904
20905 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
20906 return ira->codegen->invalid_instruction;
20907 if (!type_has_bits(dest_type)) {
20908 ir_add_error(ira, dest_type_value,
20909 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
20910 return ira->codegen->invalid_instruction;
20911 }
20912
20913
20914 IrInstruction *target = instruction->target->child;
20915 if (type_is_invalid(target->value.type))
20916 return ira->codegen->invalid_instruction;
20917
20918 return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type);
20919}
20920
20831static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,20921static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20832 IrInstructionDeclRef *instruction)20922 IrInstructionDeclRef *instruction)
20833{20923{
src/parser.cpp+8
...@@ -2779,6 +2779,7 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2779,6 +2779,7 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2779// <- ASTERISK2779// <- ASTERISK
2780// / ASTERISK22780// / ASTERISK2
2781// / LBRACKET ASTERISK RBRACKET2781// / LBRACKET ASTERISK RBRACKET
2782// / LBRACKET ASTERISK C RBRACKET
2782static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {2783static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2783 Token *asterisk = eat_token_if(pc, TokenIdStar);2784 Token *asterisk = eat_token_if(pc, TokenIdStar);
2784 if (asterisk != nullptr) {2785 if (asterisk != nullptr) {
...@@ -2804,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {...@@ -2804,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2804 return res;2805 return res;
2805 }2806 }
28062807
2808 Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
2809 if (cptr != nullptr) {
2810 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
2811 res->data.pointer_type.star_token = cptr;
2812 return res;
2813 }
2814
2807 return nullptr;2815 return nullptr;
2808}2816}
28092817
src/tokenizer.cpp+18-1
...@@ -221,6 +221,7 @@ enum TokenizeState {...@@ -221,6 +221,7 @@ enum TokenizeState {
221 TokenizeStateError,221 TokenizeStateError,
222 TokenizeStateLBracket,222 TokenizeStateLBracket,
223 TokenizeStateLBracketStar,223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
224};225};
225226
226227
...@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
846 switch (c) {847 switch (c) {
847 case '*':848 case '*':
848 t.state = TokenizeStateLBracketStar;849 t.state = TokenizeStateLBracketStar;
849 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
850 break;850 break;
851 default:851 default:
852 // reinterpret as just an lbracket852 // reinterpret as just an lbracket
...@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
857 }857 }
858 break;858 break;
859 case TokenizeStateLBracketStar:859 case TokenizeStateLBracketStar:
860 switch (c) {
861 case 'c':
862 t.state = TokenizeStateLBracketStarC;
863 set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
864 break;
865 case ']':
866 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
867 end_token(&t);
868 t.state = TokenizeStateStart;
869 break;
870 default:
871 invalid_char_error(&t, c);
872 }
873 break;
874 case TokenizeStateLBracketStarC:
860 switch (c) {875 switch (c) {
861 case ']':876 case ']':
862 end_token(&t);877 end_token(&t);
...@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
1491 case TokenizeStateLineStringContinue:1506 case TokenizeStateLineStringContinue:
1492 case TokenizeStateLineStringContinueC:1507 case TokenizeStateLineStringContinueC:
1493 case TokenizeStateLBracketStar:1508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
1494 tokenize_error(&t, "unexpected EOF");1510 tokenize_error(&t, "unexpected EOF");
1495 break;1511 break;
1496 case TokenizeStateLineComment:1512 case TokenizeStateLineComment:
...@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {...@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
1528 case TokenIdBitShiftRightEq: return ">>=";1544 case TokenIdBitShiftRightEq: return ">>=";
1529 case TokenIdBitXorEq: return "^=";1545 case TokenIdBitXorEq: return "^=";
1530 case TokenIdBracketStarBracket: return "[*]";1546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
1531 case TokenIdCharLiteral: return "CharLiteral";1548 case TokenIdCharLiteral: return "CharLiteral";
1532 case TokenIdCmpEq: return "==";1549 case TokenIdCmpEq: return "==";
1533 case TokenIdCmpGreaterOrEq: return ">=";1550 case TokenIdCmpGreaterOrEq: return ">=";
src/tokenizer.hpp+1
...@@ -29,6 +29,7 @@ enum TokenId {...@@ -29,6 +29,7 @@ enum TokenId {
29 TokenIdBitShiftRightEq,29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,30 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
32 TokenIdCharLiteral,33 TokenIdCharLiteral,
33 TokenIdCmpEq,34 TokenIdCmpEq,
34 TokenIdCmpGreaterOrEq,35 TokenIdCmpGreaterOrEq,
test/stage1/behavior/pointers.zig+6
...@@ -42,3 +42,9 @@ test "double pointer parsing" {...@@ -42,3 +42,9 @@ test "double pointer parsing" {
42fn PtrOf(comptime T: type) type {42fn PtrOf(comptime T: type) type {
43 return *T;43 return *T;
44}44}
45
46test "assigning integer to C pointer" {
47 var x: i32 = 0;
48 var ptr: [*c]u8 = 0;
49 var ptr2: [*c]u8 = x;
50}