| author | |
| committer | |
| log | 342bca7f4627454435e9f6c2d12b099f95a2fd47 |
| tree | 01b42262415f9cc16348bfaf3741e139527be790 |
| parent | d9e01be97386f008e4a4b4281658f25b50ff80f1 |
| signature |
See #10596 files changed, 78 insertions(+), 20 deletions(-)
src/analyze.cpp+1-1| ... | @@ -434,7 +434,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -434,7 +434,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 434 | uint32_t bit_offset_in_host, uint32_t host_int_bytes) | 434 | uint32_t bit_offset_in_host, uint32_t host_int_bytes) |
| 435 | { | 435 | { |
| 436 | assert(!type_is_invalid(child_type)); | 436 | assert(!type_is_invalid(child_type)); |
| 437 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); | 437 | assert(ptr_len != PtrLenUnknown || child_type->id != ZigTypeIdOpaque); |
| 438 | 438 | ||
| 439 | if (byte_alignment != 0) { | 439 | if (byte_alignment != 0) { |
| 440 | uint32_t abi_alignment = get_abi_alignment(g, child_type); | 440 | uint32_t abi_alignment = get_abi_alignment(g, child_type); |
src/codegen.cpp+2-2| ... | @@ -2657,7 +2657,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2657,7 +2657,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2657 | (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) || | 2657 | (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) || |
| 2658 | (op1->value.type->id == ZigTypeIdPointer && | 2658 | (op1->value.type->id == ZigTypeIdPointer && |
| 2659 | (op_id == IrBinOpAdd || op_id == IrBinOpSub) && | 2659 | (op_id == IrBinOpAdd || op_id == IrBinOpSub) && |
| 2660 | op1->value.type->data.pointer.ptr_len == PtrLenUnknown) | 2660 | op1->value.type->data.pointer.ptr_len != PtrLenSingle) |
| 2661 | ); | 2661 | ); |
| 2662 | ZigType *operand_type = op1->value.type; | 2662 | ZigType *operand_type = op1->value.type; |
| 2663 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; | 2663 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; |
| ... | @@ -2716,7 +2716,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2716,7 +2716,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2716 | AddSubMulMul; | 2716 | AddSubMulMul; |
| 2717 | 2717 | ||
| 2718 | if (scalar_type->id == ZigTypeIdPointer) { | 2718 | if (scalar_type->id == ZigTypeIdPointer) { |
| 2719 | assert(scalar_type->data.pointer.ptr_len == PtrLenUnknown); | 2719 | assert(scalar_type->data.pointer.ptr_len != PtrLenSingle); |
| 2720 | LLVMValueRef subscript_value; | 2720 | LLVMValueRef subscript_value; |
| 2721 | if (operand_type->id == ZigTypeIdVector) | 2721 | if (operand_type->id == ZigTypeIdVector) |
| 2722 | zig_panic("TODO: Implement vector operations on pointers."); | 2722 | zig_panic("TODO: Implement vector operations on pointers."); |
src/ir.cpp+41-5| ... | @@ -8943,7 +8943,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * | ... | @@ -8943,7 +8943,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * |
| 8943 | *errors = reallocate(*errors, old_errors_count, *errors_count); | 8943 | *errors = reallocate(*errors, old_errors_count, *errors_count); |
| 8944 | } | 8944 | } |
| 8945 | 8945 | ||
| 8946 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) { | 8946 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, |
| 8947 | IrInstruction **instructions, size_t instruction_count) | ||
| 8948 | { | ||
| 8947 | Error err; | 8949 | Error err; |
| 8948 | assert(instruction_count >= 1); | 8950 | assert(instruction_count >= 1); |
| 8949 | IrInstruction *prev_inst = instructions[0]; | 8951 | IrInstruction *prev_inst = instructions[0]; |
| ... | @@ -9260,6 +9262,19 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -9260,6 +9262,19 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 9260 | continue; | 9262 | continue; |
| 9261 | } | 9263 | } |
| 9262 | 9264 | ||
| 9265 | if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC && | ||
| 9266 | (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt)) | ||
| 9267 | { | ||
| 9268 | continue; | ||
| 9269 | } | ||
| 9270 | |||
| 9271 | if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC && | ||
| 9272 | (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt)) | ||
| 9273 | { | ||
| 9274 | prev_inst = cur_inst; | ||
| 9275 | continue; | ||
| 9276 | } | ||
| 9277 | |||
| 9263 | if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) { | 9278 | if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) { |
| 9264 | continue; | 9279 | continue; |
| 9265 | } | 9280 | } |
| ... | @@ -11852,7 +11867,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11852,7 +11867,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11852 | case ZigTypeIdBool: | 11867 | case ZigTypeIdBool: |
| 11853 | case ZigTypeIdMetaType: | 11868 | case ZigTypeIdMetaType: |
| 11854 | case ZigTypeIdVoid: | 11869 | case ZigTypeIdVoid: |
| 11855 | case ZigTypeIdPointer: | ||
| 11856 | case ZigTypeIdErrorSet: | 11870 | case ZigTypeIdErrorSet: |
| 11857 | case ZigTypeIdFn: | 11871 | case ZigTypeIdFn: |
| 11858 | case ZigTypeIdOpaque: | 11872 | case ZigTypeIdOpaque: |
| ... | @@ -11864,6 +11878,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11864,6 +11878,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11864 | operator_allowed = is_equality_cmp; | 11878 | operator_allowed = is_equality_cmp; |
| 11865 | break; | 11879 | break; |
| 11866 | 11880 | ||
| 11881 | case ZigTypeIdPointer: | ||
| 11882 | operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len != PtrLenSingle); | ||
| 11883 | break; | ||
| 11884 | |||
| 11867 | case ZigTypeIdUnreachable: | 11885 | case ZigTypeIdUnreachable: |
| 11868 | case ZigTypeIdArray: | 11886 | case ZigTypeIdArray: |
| 11869 | case ZigTypeIdStruct: | 11887 | case ZigTypeIdStruct: |
| ... | @@ -12324,6 +12342,26 @@ static bool ok_float_op(IrBinOp op) { | ... | @@ -12324,6 +12342,26 @@ static bool ok_float_op(IrBinOp op) { |
| 12324 | zig_unreachable(); | 12342 | zig_unreachable(); |
| 12325 | } | 12343 | } |
| 12326 | 12344 | ||
| 12345 | static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { | ||
| 12346 | if (lhs_type->id != ZigTypeIdPointer) | ||
| 12347 | return false; | ||
| 12348 | switch (op) { | ||
| 12349 | case IrBinOpAdd: | ||
| 12350 | case IrBinOpSub: | ||
| 12351 | break; | ||
| 12352 | default: | ||
| 12353 | return false; | ||
| 12354 | } | ||
| 12355 | switch (lhs_type->data.pointer.ptr_len) { | ||
| 12356 | case PtrLenSingle: | ||
| 12357 | return false; | ||
| 12358 | case PtrLenUnknown: | ||
| 12359 | case PtrLenC: | ||
| 12360 | break; | ||
| 12361 | } | ||
| 12362 | return true; | ||
| 12363 | } | ||
| 12364 | |||
| 12327 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 12365 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 12328 | IrInstruction *op1 = instruction->op1->child; | 12366 | IrInstruction *op1 = instruction->op1->child; |
| 12329 | if (type_is_invalid(op1->value.type)) | 12367 | if (type_is_invalid(op1->value.type)) |
| ... | @@ -12336,9 +12374,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -12336,9 +12374,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 12336 | IrBinOp op_id = instruction->op_id; | 12374 | IrBinOp op_id = instruction->op_id; |
| 12337 | 12375 | ||
| 12338 | // look for pointer math | 12376 | // look for pointer math |
| 12339 | if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown && | 12377 | if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) { |
| 12340 | (op_id == IrBinOpAdd || op_id == IrBinOpSub)) | ||
| 12341 | { | ||
| 12342 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); | 12378 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); |
| 12343 | if (casted_op2 == ira->codegen->invalid_instruction) | 12379 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 12344 | return ira->codegen->invalid_instruction; | 12380 | return ira->codegen->invalid_instruction; |
src/translate_c.cpp+5-3| ... | @@ -1677,7 +1677,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im | ... | @@ -1677,7 +1677,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1677 | return node; | 1677 | return node; |
| 1678 | } | 1678 | } |
| 1679 | case CK_NullToPointer: | 1679 | case CK_NullToPointer: |
| 1680 | return trans_create_node(c, NodeTypeNullLiteral); | 1680 | return trans_create_node_unsigned(c, 0); |
| 1681 | case CK_Dependent: | 1681 | case CK_Dependent: |
| 1682 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); | 1682 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); |
| 1683 | return nullptr; | 1683 | return nullptr; |
| ... | @@ -2409,7 +2409,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2409,7 +2409,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2409 | case BuiltinType::Float16: | 2409 | case BuiltinType::Float16: |
| 2410 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); | 2410 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); |
| 2411 | case BuiltinType::NullPtr: | 2411 | case BuiltinType::NullPtr: |
| 2412 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | 2412 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, |
| 2413 | trans_create_node_unsigned(c, 0)); | ||
| 2413 | 2414 | ||
| 2414 | case BuiltinType::Void: | 2415 | case BuiltinType::Void: |
| 2415 | case BuiltinType::Half: | 2416 | case BuiltinType::Half: |
| ... | @@ -2494,7 +2495,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2494,7 +2495,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2494 | break; | 2495 | break; |
| 2495 | } | 2496 | } |
| 2496 | case Type::Pointer: | 2497 | case Type::Pointer: |
| 2497 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | 2498 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, |
| 2499 | trans_create_node_unsigned(c, 0)); | ||
| 2498 | 2500 | ||
| 2499 | case Type::Typedef: | 2501 | case Type::Typedef: |
| 2500 | { | 2502 | { |
test/stage1/behavior/pointers.zig+20| ... | @@ -56,3 +56,23 @@ test "implicit cast single item pointer to C pointer and back" { | ... | @@ -56,3 +56,23 @@ test "implicit cast single item pointer to C pointer and back" { |
| 56 | z.* += 1; | 56 | z.* += 1; |
| 57 | expect(y == 12); | 57 | expect(y == 12); |
| 58 | } | 58 | } |
| 59 | |||
| 60 | test "C pointer comparison and arithmetic" { | ||
| 61 | var one: usize = 1; | ||
| 62 | var ptr1: [*c]u8 = 0; | ||
| 63 | var ptr2 = ptr1 + 10; | ||
| 64 | expect(ptr1 == 0); | ||
| 65 | expect(ptr1 >= 0); | ||
| 66 | expect(ptr1 <= 0); | ||
| 67 | expect(ptr1 < 1); | ||
| 68 | expect(ptr1 < one); | ||
| 69 | expect(1 > ptr1); | ||
| 70 | expect(one > ptr1); | ||
| 71 | expect(ptr1 < ptr2); | ||
| 72 | expect(ptr2 > ptr1); | ||
| 73 | expect(ptr2 >= 10); | ||
| 74 | expect(ptr2 == 10); | ||
| 75 | expect(ptr2 <= 10); | ||
| 76 | ptr2 -= 10; | ||
| 77 | expect(ptr1 == ptr2); | ||
| 78 | } |
test/translate_c.zig+9-9| ... | @@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 610 | , | 610 | , |
| 611 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int { | 611 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int { |
| 612 | \\ if ((a != 0) and (b != 0)) return 0; | 612 | \\ if ((a != 0) and (b != 0)) return 0; |
| 613 | \\ if ((b != 0) and (c != null)) return 1; | 613 | \\ if ((b != 0) and (c != 0)) return 1; |
| 614 | \\ if ((a != 0) and (c != null)) return 2; | 614 | \\ if ((a != 0) and (c != 0)) return 2; |
| 615 | \\ if ((a != 0) or (b != 0)) return 3; | 615 | \\ if ((a != 0) or (b != 0)) return 3; |
| 616 | \\ if ((b != 0) or (c != null)) return 4; | 616 | \\ if ((b != 0) or (c != 0)) return 4; |
| 617 | \\ if ((a != 0) or (c != null)) return 5; | 617 | \\ if ((a != 0) or (c != 0)) return 5; |
| 618 | \\ return 6; | 618 | \\ return 6; |
| 619 | \\} | 619 | \\} |
| 620 | ); | 620 | ); |
| ... | @@ -778,7 +778,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -778,7 +778,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 778 | \\} | 778 | \\} |
| 779 | , | 779 | , |
| 780 | \\pub export fn foo() [*c]c_int { | 780 | \\pub export fn foo() [*c]c_int { |
| 781 | \\ return null; | 781 | \\ return 0; |
| 782 | \\} | 782 | \\} |
| 783 | ); | 783 | ); |
| 784 | 784 | ||
| ... | @@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1280 | \\ return !(a == 0); | 1280 | \\ return !(a == 0); |
| 1281 | \\ return !(a != 0); | 1281 | \\ return !(a != 0); |
| 1282 | \\ return !(b != 0); | 1282 | \\ return !(b != 0); |
| 1283 | \\ return !(c != null); | 1283 | \\ return !(c != 0); |
| 1284 | \\} | 1284 | \\} |
| 1285 | ); | 1285 | ); |
| 1286 | 1286 | ||
| ... | @@ -1337,7 +1337,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1337,7 +1337,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1337 | \\pub fn if_none_bool(a: c_int, b: f32, c: [*c]c_void, d: enum_SomeEnum) c_int { | 1337 | \\pub fn if_none_bool(a: c_int, b: f32, c: [*c]c_void, d: enum_SomeEnum) c_int { |
| 1338 | \\ if (a != 0) return 0; | 1338 | \\ if (a != 0) return 0; |
| 1339 | \\ if (b != 0) return 1; | 1339 | \\ if (b != 0) return 1; |
| 1340 | \\ if (c != null) return 2; | 1340 | \\ if (c != 0) return 2; |
| 1341 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; | 1341 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; |
| 1342 | \\ return 4; | 1342 | \\ return 4; |
| 1343 | \\} | 1343 | \\} |
| ... | @@ -1354,7 +1354,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1354,7 +1354,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1354 | \\pub fn while_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int { | 1354 | \\pub fn while_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int { |
| 1355 | \\ while (a != 0) return 0; | 1355 | \\ while (a != 0) return 0; |
| 1356 | \\ while (b != 0) return 1; | 1356 | \\ while (b != 0) return 1; |
| 1357 | \\ while (c != null) return 2; | 1357 | \\ while (c != 0) return 2; |
| 1358 | \\ return 3; | 1358 | \\ return 3; |
| 1359 | \\} | 1359 | \\} |
| 1360 | ); | 1360 | ); |
| ... | @@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1370 | \\pub fn for_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int { | 1370 | \\pub fn for_none_bool(a: c_int, b: f32, c: [*c]c_void) c_int { |
| 1371 | \\ while (a != 0) return 0; | 1371 | \\ while (a != 0) return 0; |
| 1372 | \\ while (b != 0) return 1; | 1372 | \\ while (b != 0) return 1; |
| 1373 | \\ while (c != null) return 2; | 1373 | \\ while (c != 0) return 2; |
| 1374 | \\ return 3; | 1374 | \\ return 3; |
| 1375 | \\} | 1375 | \\} |
| 1376 | ); | 1376 | ); |