| ... | ... | @@ -1010,17 +1010,23 @@ fn buildFlexibleArrayFn( |
| 1010 | 1010 | const bit_offset = layout.getFieldOffset(field_index); // this is a target-specific constant based on the struct layout |
| 1011 | 1011 | const byte_offset = bit_offset / 8; |
| 1012 | 1012 | |
| 1013 | | const casted_self = try Tag.ptr_cast.create(c.arena, .{ |
| 1013 | const casted_self = try Tag.as.create(c.arena, .{ |
| 1014 | 1014 | .lhs = intermediate_type_ident, |
| 1015 | | .rhs = self_param, |
| 1015 | .rhs = try Tag.ptr_cast.create(c.arena, self_param), |
| 1016 | 1016 | }); |
| 1017 | 1017 | const field_offset = try transCreateNodeNumber(c, byte_offset, .int); |
| 1018 | 1018 | const field_ptr = try Tag.add.create(c.arena, .{ .lhs = casted_self, .rhs = field_offset }); |
| 1019 | 1019 | |
| 1020 | | const alignment = try Tag.alignof.create(c.arena, element_type); |
| 1021 | | |
| 1022 | | const ptr_val = try Tag.align_cast.create(c.arena, .{ .lhs = alignment, .rhs = field_ptr }); |
| 1023 | | const ptr_cast = try Tag.ptr_cast.create(c.arena, .{ .lhs = return_type_ident, .rhs = ptr_val }); |
| 1020 | const ptr_cast = try Tag.as.create(c.arena, .{ |
| 1021 | .lhs = return_type_ident, |
| 1022 | .rhs = try Tag.ptr_cast.create( |
| 1023 | c.arena, |
| 1024 | try Tag.align_cast.create( |
| 1025 | c.arena, |
| 1026 | field_ptr, |
| 1027 | ), |
| 1028 | ), |
| 1029 | }); |
| 1024 | 1030 | const return_stmt = try Tag.@"return".create(c.arena, ptr_cast); |
| 1025 | 1031 | try block_scope.statements.append(return_stmt); |
| 1026 | 1032 | |
| ... | ... | @@ -1579,14 +1585,14 @@ fn transOffsetOfExpr( |
| 1579 | 1585 | /// pointer arithmetic expressions, where wraparound will ensure we get the correct value. |
| 1580 | 1586 | /// node -> @bitCast(usize, @intCast(isize, node)) |
| 1581 | 1587 | fn usizeCastForWrappingPtrArithmetic(gpa: mem.Allocator, node: Node) TransError!Node { |
| 1582 | | const intcast_node = try Tag.int_cast.create(gpa, .{ |
| 1588 | const intcast_node = try Tag.as.create(gpa, .{ |
| 1583 | 1589 | .lhs = try Tag.type.create(gpa, "isize"), |
| 1584 | | .rhs = node, |
| 1590 | .rhs = try Tag.int_cast.create(gpa, node), |
| 1585 | 1591 | }); |
| 1586 | 1592 | |
| 1587 | | return Tag.bit_cast.create(gpa, .{ |
| 1593 | return Tag.as.create(gpa, .{ |
| 1588 | 1594 | .lhs = try Tag.type.create(gpa, "usize"), |
| 1589 | | .rhs = intcast_node, |
| 1595 | .rhs = try Tag.bit_cast.create(gpa, intcast_node), |
| 1590 | 1596 | }); |
| 1591 | 1597 | } |
| 1592 | 1598 | |
| ... | ... | @@ -1781,7 +1787,10 @@ fn transBinaryOperator( |
| 1781 | 1787 | const elem_type = c_pointer.castTag(.c_pointer).?.data.elem_type; |
| 1782 | 1788 | const sizeof = try Tag.sizeof.create(c.arena, elem_type); |
| 1783 | 1789 | |
| 1784 | | const bitcast = try Tag.bit_cast.create(c.arena, .{ .lhs = ptrdiff_type, .rhs = infixOpNode }); |
| 1790 | const bitcast = try Tag.as.create(c.arena, .{ |
| 1791 | .lhs = ptrdiff_type, |
| 1792 | .rhs = try Tag.bit_cast.create(c.arena, infixOpNode), |
| 1793 | }); |
| 1785 | 1794 | |
| 1786 | 1795 | return Tag.div_exact.create(c.arena, .{ |
| 1787 | 1796 | .lhs = bitcast, |
| ... | ... | @@ -2310,7 +2319,7 @@ fn transIntegerLiteral( |
| 2310 | 2319 | // unsigned char y = 256; |
| 2311 | 2320 | // How this gets evaluated is the 256 is an integer, which gets truncated to signed char, then bit-casted |
| 2312 | 2321 | // to unsigned char, resulting in 0. In order for this to work, we have to emit this zig code: |
| 2313 | | // var y = @bitCast(u8, @truncate(i8, @as(c_int, 256))); |
| 2322 | // var y = @as(u8, @bitCast(@as(i8, @truncate(@as(c_int, 256))))); |
| 2314 | 2323 | // Ideally in translate-c we could flatten this out to simply: |
| 2315 | 2324 | // var y: u8 = 0; |
| 2316 | 2325 | // But the first step is to be correct, and the next step is to make the output more elegant. |
| ... | ... | @@ -2501,7 +2510,10 @@ fn transCCast( |
| 2501 | 2510 | .lt => { |
| 2502 | 2511 | // @truncate(SameSignSmallerInt, src_int_expr) |
| 2503 | 2512 | const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); |
| 2504 | | src_int_expr = try Tag.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); |
| 2513 | src_int_expr = try Tag.as.create(c.arena, .{ |
| 2514 | .lhs = ty_node, |
| 2515 | .rhs = try Tag.truncate.create(c.arena, src_int_expr), |
| 2516 | }); |
| 2505 | 2517 | }, |
| 2506 | 2518 | .gt => { |
| 2507 | 2519 | // @as(SameSignBiggerInt, src_int_expr) |
| ... | ... | @@ -2512,36 +2524,57 @@ fn transCCast( |
| 2512 | 2524 | // src_int_expr = src_int_expr |
| 2513 | 2525 | }, |
| 2514 | 2526 | } |
| 2515 | | // @bitCast(dest_type, intermediate_value) |
| 2516 | | return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr }); |
| 2527 | // @as(dest_type, @bitCast(intermediate_value)) |
| 2528 | return Tag.as.create(c.arena, .{ |
| 2529 | .lhs = dst_node, |
| 2530 | .rhs = try Tag.bit_cast.create(c.arena, src_int_expr), |
| 2531 | }); |
| 2517 | 2532 | } |
| 2518 | 2533 | if (cIsVector(src_type) or cIsVector(dst_type)) { |
| 2519 | 2534 | // C cast where at least 1 operand is a vector requires them to be same size |
| 2520 | | // @bitCast(dest_type, val) |
| 2521 | | return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 2535 | // @as(dest_type, @bitCast(val)) |
| 2536 | return Tag.as.create(c.arena, .{ |
| 2537 | .lhs = dst_node, |
| 2538 | .rhs = try Tag.bit_cast.create(c.arena, expr), |
| 2539 | }); |
| 2522 | 2540 | } |
| 2523 | 2541 | if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { |
| 2524 | 2542 | // @intCast(dest_type, @intFromPtr(val)) |
| 2525 | 2543 | const int_from_ptr = try Tag.int_from_ptr.create(c.arena, expr); |
| 2526 | | return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = int_from_ptr }); |
| 2544 | return Tag.as.create(c.arena, .{ |
| 2545 | .lhs = dst_node, |
| 2546 | .rhs = try Tag.int_cast.create(c.arena, int_from_ptr), |
| 2547 | }); |
| 2527 | 2548 | } |
| 2528 | 2549 | if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { |
| 2529 | | // @ptrFromInt(dest_type, val) |
| 2530 | | return Tag.ptr_from_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 2550 | // @as(dest_type, @ptrFromInt(val)) |
| 2551 | return Tag.as.create(c.arena, .{ |
| 2552 | .lhs = dst_node, |
| 2553 | .rhs = try Tag.ptr_from_int.create(c.arena, expr), |
| 2554 | }); |
| 2531 | 2555 | } |
| 2532 | 2556 | if (cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 2533 | | // @floatCast(dest_type, val) |
| 2534 | | return Tag.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 2557 | // @as(dest_type, @floatCast(val)) |
| 2558 | return Tag.as.create(c.arena, .{ |
| 2559 | .lhs = dst_node, |
| 2560 | .rhs = try Tag.float_cast.create(c.arena, expr), |
| 2561 | }); |
| 2535 | 2562 | } |
| 2536 | 2563 | if (cIsFloating(src_type) and !cIsFloating(dst_type)) { |
| 2537 | | // @intFromFloat(dest_type, val) |
| 2538 | | return Tag.int_from_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 2564 | // @as(dest_type, @intFromFloat(val)) |
| 2565 | return Tag.as.create(c.arena, .{ |
| 2566 | .lhs = dst_node, |
| 2567 | .rhs = try Tag.int_from_float.create(c.arena, expr), |
| 2568 | }); |
| 2539 | 2569 | } |
| 2540 | 2570 | if (!cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 2541 | 2571 | var rhs = expr; |
| 2542 | 2572 | if (qualTypeIsBoolean(src_type)) rhs = try Tag.int_from_bool.create(c.arena, expr); |
| 2543 | | // @floatFromInt(dest_type, val) |
| 2544 | | return Tag.float_from_int.create(c.arena, .{ .lhs = dst_node, .rhs = rhs }); |
| 2573 | // @as(dest_type, @floatFromInt(val)) |
| 2574 | return Tag.as.create(c.arena, .{ |
| 2575 | .lhs = dst_node, |
| 2576 | .rhs = try Tag.float_from_int.create(c.arena, rhs), |
| 2577 | }); |
| 2545 | 2578 | } |
| 2546 | 2579 | if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { |
| 2547 | 2580 | // @intFromBool returns a u1 |
| ... | ... | @@ -3487,9 +3520,9 @@ fn transSignedArrayAccess( |
| 3487 | 3520 | |
| 3488 | 3521 | const then_value = try Tag.add.create(c.arena, .{ |
| 3489 | 3522 | .lhs = container_node, |
| 3490 | | .rhs = try Tag.int_cast.create(c.arena, .{ |
| 3523 | .rhs = try Tag.as.create(c.arena, .{ |
| 3491 | 3524 | .lhs = try Tag.type.create(c.arena, "usize"), |
| 3492 | | .rhs = tmp_ref, |
| 3525 | .rhs = try Tag.int_cast.create(c.arena, tmp_ref), |
| 3493 | 3526 | }), |
| 3494 | 3527 | }); |
| 3495 | 3528 | |
| ... | ... | @@ -3499,17 +3532,17 @@ fn transSignedArrayAccess( |
| 3499 | 3532 | }); |
| 3500 | 3533 | |
| 3501 | 3534 | const minuend = container_node; |
| 3502 | | const signed_size = try Tag.int_cast.create(c.arena, .{ |
| 3535 | const signed_size = try Tag.as.create(c.arena, .{ |
| 3503 | 3536 | .lhs = try Tag.type.create(c.arena, "isize"), |
| 3504 | | .rhs = tmp_ref, |
| 3537 | .rhs = try Tag.int_cast.create(c.arena, tmp_ref), |
| 3505 | 3538 | }); |
| 3506 | 3539 | const to_cast = try Tag.add_wrap.create(c.arena, .{ |
| 3507 | 3540 | .lhs = signed_size, |
| 3508 | 3541 | .rhs = try Tag.negate.create(c.arena, Tag.one_literal.init()), |
| 3509 | 3542 | }); |
| 3510 | | const bitcast_node = try Tag.bit_cast.create(c.arena, .{ |
| 3543 | const bitcast_node = try Tag.as.create(c.arena, .{ |
| 3511 | 3544 | .lhs = try Tag.type.create(c.arena, "usize"), |
| 3512 | | .rhs = to_cast, |
| 3545 | .rhs = try Tag.bit_cast.create(c.arena, to_cast), |
| 3513 | 3546 | }); |
| 3514 | 3547 | const subtrahend = try Tag.bit_not.create(c.arena, bitcast_node); |
| 3515 | 3548 | const difference = try Tag.sub.create(c.arena, .{ |
| ... | ... | @@ -3566,7 +3599,13 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip |
| 3566 | 3599 | const rhs = if (is_longlong or is_signed) blk: { |
| 3567 | 3600 | // check if long long first so that signed long long doesn't just become unsigned long long |
| 3568 | 3601 | const typeid_node = if (is_longlong) try Tag.type.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, subscr_qt, false); |
| 3569 | | break :blk try Tag.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used) }); |
| 3602 | break :blk try Tag.as.create(c.arena, .{ |
| 3603 | .lhs = typeid_node, |
| 3604 | .rhs = try Tag.int_cast.create( |
| 3605 | c.arena, |
| 3606 | try transExpr(c, scope, subscr_expr, .used), |
| 3607 | ), |
| 3608 | }); |
| 3570 | 3609 | } else try transExpr(c, scope, subscr_expr, .used); |
| 3571 | 3610 | |
| 3572 | 3611 | const node = try Tag.array_access.create(c.arena, .{ |
| ... | ... | @@ -3968,8 +4007,7 @@ fn transCreateCompoundAssign( |
| 3968 | 4007 | } |
| 3969 | 4008 | |
| 3970 | 4009 | if (is_shift) { |
| 3971 | | const cast_to_type = try qualTypeToLog2IntRef(c, scope, rhs_qt, loc); |
| 3972 | | rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 4010 | rhs_node = try Tag.int_cast.create(c.arena, rhs_node); |
| 3973 | 4011 | } else if (requires_int_cast) { |
| 3974 | 4012 | rhs_node = try transCCast(c, scope, loc, lhs_qt, rhs_qt, rhs_node); |
| 3975 | 4013 | } |
| ... | ... | @@ -4008,8 +4046,7 @@ fn transCreateCompoundAssign( |
| 4008 | 4046 | try block_scope.statements.append(assign); |
| 4009 | 4047 | } else { |
| 4010 | 4048 | if (is_shift) { |
| 4011 | | const cast_to_type = try qualTypeToLog2IntRef(c, &block_scope.base, rhs_qt, loc); |
| 4012 | | rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 4049 | rhs_node = try Tag.int_cast.create(c.arena, rhs_node); |
| 4013 | 4050 | } else if (requires_int_cast) { |
| 4014 | 4051 | rhs_node = try transCCast(c, &block_scope.base, loc, lhs_qt, rhs_qt, rhs_node); |
| 4015 | 4052 | } |
| ... | ... | @@ -4029,7 +4066,10 @@ fn transCreateCompoundAssign( |
| 4029 | 4066 | // Casting away const or volatile requires us to use @ptrFromInt |
| 4030 | 4067 | fn removeCVQualifiers(c: *Context, dst_type_node: Node, expr: Node) Error!Node { |
| 4031 | 4068 | const int_from_ptr = try Tag.int_from_ptr.create(c.arena, expr); |
| 4032 | | return Tag.ptr_from_int.create(c.arena, .{ .lhs = dst_type_node, .rhs = int_from_ptr }); |
| 4069 | return Tag.as.create(c.arena, .{ |
| 4070 | .lhs = dst_type_node, |
| 4071 | .rhs = try Tag.ptr_from_int.create(c.arena, int_from_ptr), |
| 4072 | }); |
| 4033 | 4073 | } |
| 4034 | 4074 | |
| 4035 | 4075 | fn transCPtrCast( |
| ... | ... | @@ -4062,11 +4102,12 @@ fn transCPtrCast( |
| 4062 | 4102 | // For opaque types a ptrCast is enough |
| 4063 | 4103 | expr |
| 4064 | 4104 | else blk: { |
| 4065 | | const alignof = try Tag.std_meta_alignment.create(c.arena, dst_type_node); |
| 4066 | | const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr }); |
| 4067 | | break :blk align_cast; |
| 4105 | break :blk try Tag.align_cast.create(c.arena, expr); |
| 4068 | 4106 | }; |
| 4069 | | return Tag.ptr_cast.create(c.arena, .{ .lhs = dst_type_node, .rhs = rhs }); |
| 4107 | return Tag.as.create(c.arena, .{ |
| 4108 | .lhs = dst_type_node, |
| 4109 | .rhs = try Tag.ptr_cast.create(c.arena, rhs), |
| 4110 | }); |
| 4070 | 4111 | } |
| 4071 | 4112 | } |
| 4072 | 4113 | |
| ... | ... | @@ -4337,19 +4378,6 @@ fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType) !u32 { |
| 4337 | 4378 | } |
| 4338 | 4379 | } |
| 4339 | 4380 | |
| 4340 | | fn qualTypeToLog2IntRef(c: *Context, scope: *Scope, qt: clang.QualType, source_loc: clang.SourceLocation) !Node { |
| 4341 | | const int_bit_width = try qualTypeIntBitWidth(c, qt); |
| 4342 | | |
| 4343 | | if (int_bit_width != 0) { |
| 4344 | | // we can perform the log2 now. |
| 4345 | | const cast_bit_width = math.log2_int(u64, int_bit_width); |
| 4346 | | return Tag.log2_int_type.create(c.arena, cast_bit_width); |
| 4347 | | } |
| 4348 | | |
| 4349 | | const zig_type = try transQualType(c, scope, qt, source_loc); |
| 4350 | | return Tag.std_math_Log2Int.create(c.arena, zig_type); |
| 4351 | | } |
| 4352 | | |
| 4353 | 4381 | fn qualTypeChildIsFnProto(qt: clang.QualType) bool { |
| 4354 | 4382 | const ty = qualTypeCanon(qt); |
| 4355 | 4383 | |
| ... | ... | @@ -4731,14 +4759,12 @@ fn transCreateNodeShiftOp( |
| 4731 | 4759 | |
| 4732 | 4760 | const lhs_expr = stmt.getLHS(); |
| 4733 | 4761 | const rhs_expr = stmt.getRHS(); |
| 4734 | | const rhs_location = rhs_expr.getBeginLoc(); |
| 4735 | 4762 | // lhs >> @as(u5, rh) |
| 4736 | 4763 | |
| 4737 | 4764 | const lhs = try transExpr(c, scope, lhs_expr, .used); |
| 4738 | 4765 | |
| 4739 | | const rhs_type = try qualTypeToLog2IntRef(c, scope, stmt.getType(), rhs_location); |
| 4740 | 4766 | const rhs = try transExprCoercing(c, scope, rhs_expr, .used); |
| 4741 | | const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs }); |
| 4767 | const rhs_casted = try Tag.int_cast.create(c.arena, rhs); |
| 4742 | 4768 | |
| 4743 | 4769 | return transCreateNodeInfixOp(c, op, lhs, rhs_casted, used); |
| 4744 | 4770 | } |
| ... | ... | @@ -6513,9 +6539,9 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6513 | 6539 | }, |
| 6514 | 6540 | .LBracket => { |
| 6515 | 6541 | const index_val = try macroIntFromBool(c, try parseCExpr(c, m, scope)); |
| 6516 | | const index = try Tag.int_cast.create(c.arena, .{ |
| 6542 | const index = try Tag.as.create(c.arena, .{ |
| 6517 | 6543 | .lhs = try Tag.type.create(c.arena, "usize"), |
| 6518 | | .rhs = index_val, |
| 6544 | .rhs = try Tag.int_cast.create(c.arena, index_val), |
| 6519 | 6545 | }); |
| 6520 | 6546 | node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index }); |
| 6521 | 6547 | try m.skip(c, .RBracket); |