@@ -856,6 +856,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
856
856
return IrInstructionIdSqrt;
857
857
}
858
858
859
+ static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
860
+ return IrInstructionIdBswap;
861
+ }
862
+
859
863
static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
860
864
return IrInstructionIdCheckRuntimeScope;
861
865
}
@@ -2705,6 +2709,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc
2705
2709
return &instruction->base;
2706
2710
}
2707
2711
2712
+ static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
2713
+ IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node);
2714
+ instruction->type = type;
2715
+ instruction->op = op;
2716
+
2717
+ if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
2718
+ ir_ref_instruction(op, irb->current_basic_block);
2719
+
2720
+ return &instruction->base;
2721
+ }
2722
+
2708
2723
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
2709
2724
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
2710
2725
instruction->scope_is_comptime = scope_is_comptime;
@@ -4689,6 +4704,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4689
4704
IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
4690
4705
return ir_lval_wrap(irb, scope, result, lval);
4691
4706
}
4707
+ case BuiltinFnIdBswap:
4708
+ {
4709
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4710
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4711
+ if (arg0_value == irb->codegen->invalid_instruction)
4712
+ return arg0_value;
4713
+
4714
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4715
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4716
+ if (arg1_value == irb->codegen->invalid_instruction)
4717
+ return arg1_value;
4718
+
4719
+ IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
4720
+ return ir_lval_wrap(irb, scope, result, lval);
4721
+ }
4692
4722
}
4693
4723
zig_unreachable();
4694
4724
}
@@ -13674,18 +13704,55 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
13674
13704
return ErrorNone;
13675
13705
}
13676
13706
13677
- if (dst_size > src_size) {
13678
- ir_add_error_node(ira, source_node,
13679
- buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
13680
- dst_size, buf_ptr(&pointee->type->name), src_size));
13681
- return ErrorSemanticAnalyzeFail;
13707
+ if (dst_size <= src_size) {
13708
+ Buf buf = BUF_INIT;
13709
+ buf_resize(&buf, src_size);
13710
+ buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
13711
+ buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
13712
+ return ErrorNone;
13682
13713
}
13683
13714
13684
- Buf buf = BUF_INIT;
13685
- buf_resize(&buf, src_size);
13686
- buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
13687
- buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
13688
- return ErrorNone;
13715
+ switch (ptr_val->data.x_ptr.special) {
13716
+ case ConstPtrSpecialInvalid:
13717
+ zig_unreachable();
13718
+ case ConstPtrSpecialRef: {
13719
+ ir_add_error_node(ira, source_node,
13720
+ buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
13721
+ dst_size, buf_ptr(&pointee->type->name), src_size));
13722
+ return ErrorSemanticAnalyzeFail;
13723
+ }
13724
+ case ConstPtrSpecialBaseArray: {
13725
+ ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
13726
+ assert(array_val->type->id == ZigTypeIdArray);
13727
+ if (array_val->data.x_array.special != ConstArraySpecialNone)
13728
+ zig_panic("TODO");
13729
+ size_t elem_size = src_size;
13730
+ src_size = elem_size *
13731
+ (array_val->type->data.array.len - ptr_val->data.x_ptr.data.base_array.elem_index);
13732
+ if (dst_size > src_size) {
13733
+ ir_add_error_node(ira, source_node,
13734
+ buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
13735
+ dst_size, buf_ptr(&array_val->type->name), ptr_val->data.x_ptr.data.base_array.elem_index,
13736
+ src_size));
13737
+ return ErrorSemanticAnalyzeFail;
13738
+ }
13739
+ size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
13740
+ Buf buf = BUF_INIT;
13741
+ buf_resize(&buf, elem_count * elem_size);
13742
+ for (size_t i = 0; i < elem_count; i += 1) {
13743
+ ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];
13744
+ buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
13745
+ }
13746
+ buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
13747
+ return ErrorNone;
13748
+ }
13749
+ case ConstPtrSpecialBaseStruct:
13750
+ case ConstPtrSpecialDiscard:
13751
+ case ConstPtrSpecialHardCodedAddr:
13752
+ case ConstPtrSpecialFunction:
13753
+ zig_panic("TODO");
13754
+ }
13755
+ zig_unreachable();
13689
13756
}
13690
13757
13691
13758
static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
@@ -18054,6 +18121,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
18054
18121
return ira->codegen->invalid_instruction;
18055
18122
}
18056
18123
18124
+ if (src_type->data.integral.bit_count == 0) {
18125
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18126
+ bigint_init_unsigned(&result->value.data.x_bigint, 0);
18127
+ return result;
18128
+ }
18129
+
18057
18130
if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
18058
18131
const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
18059
18132
ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
@@ -20299,6 +20372,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
20299
20372
return ira->codegen->invalid_instruction;
20300
20373
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
20301
20374
return ira->codegen->invalid_instruction;
20375
+ if (!type_has_bits(child_type)) {
20376
+ align_bytes = 0;
20377
+ }
20302
20378
} else {
20303
20379
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
20304
20380
return ira->codegen->invalid_instruction;
@@ -20898,6 +20974,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
20898
20974
return result;
20899
20975
}
20900
20976
20977
+ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
20978
+ ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
20979
+ if (type_is_invalid(int_type))
20980
+ return ira->codegen->invalid_instruction;
20981
+
20982
+ IrInstruction *op = instruction->op->child;
20983
+ if (type_is_invalid(op->value.type))
20984
+ return ira->codegen->invalid_instruction;
20985
+
20986
+ if (int_type->id != ZigTypeIdInt) {
20987
+ ir_add_error(ira, instruction->type,
20988
+ buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
20989
+ return ira->codegen->invalid_instruction;
20990
+ }
20991
+
20992
+ if (int_type->data.integral.bit_count % 8 != 0) {
20993
+ ir_add_error(ira, instruction->type,
20994
+ buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
20995
+ buf_ptr(&int_type->name), int_type->data.integral.bit_count));
20996
+ return ira->codegen->invalid_instruction;
20997
+ }
20998
+
20999
+ IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
21000
+ if (type_is_invalid(casted_op->value.type))
21001
+ return ira->codegen->invalid_instruction;
21002
+
21003
+ if (int_type->data.integral.bit_count == 0) {
21004
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
21005
+ bigint_init_unsigned(&result->value.data.x_bigint, 0);
21006
+ return result;
21007
+ }
21008
+
21009
+ if (int_type->data.integral.bit_count == 8) {
21010
+ return casted_op;
21011
+ }
21012
+
21013
+ if (instr_is_comptime(casted_op)) {
21014
+ ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
21015
+ if (!val)
21016
+ return ira->codegen->invalid_instruction;
21017
+
21018
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
21019
+ size_t buf_size = int_type->data.integral.bit_count / 8;
21020
+ uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);
21021
+ bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
21022
+ bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
21023
+ int_type->data.integral.is_signed);
21024
+ return result;
21025
+ }
21026
+
21027
+ IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
21028
+ instruction->base.source_node, nullptr, casted_op);
21029
+ result->value.type = int_type;
21030
+ return result;
21031
+ }
21032
+
21033
+
20901
21034
static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
20902
21035
Error err;
20903
21036
IrInstruction *target = instruction->target->child;
@@ -21233,6 +21366,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21233
21366
return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
21234
21367
case IrInstructionIdSqrt:
21235
21368
return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
21369
+ case IrInstructionIdBswap:
21370
+ return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
21236
21371
case IrInstructionIdIntToErr:
21237
21372
return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
21238
21373
case IrInstructionIdErrToInt:
@@ -21454,6 +21589,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21454
21589
case IrInstructionIdCoroPromise:
21455
21590
case IrInstructionIdPromiseResultType:
21456
21591
case IrInstructionIdSqrt:
21592
+ case IrInstructionIdBswap:
21457
21593
case IrInstructionIdAtomicLoad:
21458
21594
case IrInstructionIdIntCast:
21459
21595
case IrInstructionIdFloatCast:
0 commit comments