aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp9
-rw-r--r--src/bignum.cpp74
-rw-r--r--src/bignum.hpp5
-rw-r--r--src/codegen.cpp11
-rw-r--r--src/ir.cpp263
-rw-r--r--src/ir_print.cpp15
6 files changed, 376 insertions, 1 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index b3e8e6e426..7a9dcdc369 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1216,6 +1216,7 @@ enum BuiltinFnId {
BuiltinFnIdSetGlobalLinkage,
BuiltinFnIdPanic,
BuiltinFnIdPtrCast,
+ BuiltinFnIdBitCast,
BuiltinFnIdIntToPtr,
BuiltinFnIdEnumTagName,
BuiltinFnIdFieldParentPtr,
@@ -1800,6 +1801,7 @@ enum IrInstructionId {
IrInstructionIdTestComptime,
IrInstructionIdInitEnum,
IrInstructionIdPtrCast,
+ IrInstructionIdBitCast,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
IrInstructionIdPtrToInt,
@@ -2448,6 +2450,13 @@ struct IrInstructionPtrCast {
IrInstruction *ptr;
};
+struct IrInstructionBitCast {
+ IrInstruction base;
+
+ IrInstruction *dest_type;
+ IrInstruction *value;
+};
+
struct IrInstructionWidenOrShorten {
IrInstruction base;
diff --git a/src/bignum.cpp b/src/bignum.cpp
index e963b71ba3..e1848aafc2 100644
--- a/src/bignum.cpp
+++ b/src/bignum.cpp
@@ -459,3 +459,77 @@ uint32_t bignum_clz(BigNum *bignum, uint32_t bit_count) {
}
return result;
}
+
+void bignum_write_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian) {
+ assert(bn->kind == BigNumKindInt);
+ uint64_t x = bignum_to_twos_complement(bn);
+
+ int byte_count = (bit_count + 7) / 8;
+ for (int i = 0; i < byte_count; i += 1) {
+ uint8_t le_byte = (x >> (i * 8)) & 0xff;
+ if (is_big_endian) {
+ buf[byte_count - i - 1] = le_byte;
+ } else {
+ buf[i] = le_byte;
+ }
+ }
+}
+
+void bignum_read_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian, bool is_signed) {
+ int byte_count = (bit_count + 7) / 8;
+
+ uint64_t twos_comp = 0;
+ for (int i = 0; i < byte_count; i += 1) {
+ uint8_t be_byte;
+ if (is_big_endian) {
+ be_byte = buf[i];
+ } else {
+ be_byte = buf[byte_count - i - 1];
+ }
+
+ twos_comp <<= 8;
+ twos_comp |= be_byte;
+ }
+
+ uint8_t be_byte = buf[is_big_endian ? 0 : byte_count - 1];
+ if (is_signed && ((be_byte >> 7) & 0x1) != 0) {
+ bn->is_negative = true;
+ uint64_t mask = 0;
+ for (int i = 0; i < bit_count; i += 1) {
+ mask <<= 1;
+ mask |= 1;
+ }
+ bn->data.x_uint = ((~twos_comp) & mask) + 1;
+ } else {
+ bn->data.x_uint = twos_comp;
+ }
+ bn->kind = BigNumKindInt;
+}
+
+void bignum_write_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian) {
+ assert(bn->kind == BigNumKindFloat);
+ if (bit_count == 32) {
+ float f32 = bn->data.x_float;
+ memcpy(buf, &f32, 4);
+ } else if (bit_count == 64) {
+ double f64 = bn->data.x_float;
+ memcpy(buf, &f64, 8);
+ } else {
+ zig_unreachable();
+ }
+}
+
+void bignum_read_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian) {
+ bn->kind = BigNumKindFloat;
+ if (bit_count == 32) {
+ float f32;
+ memcpy(&f32, buf, 4);
+ bn->data.x_float = f32;
+ } else if (bit_count == 64) {
+ double f64;
+ memcpy(&f64, buf, 8);
+ bn->data.x_float = f64;
+ } else {
+ zig_unreachable();
+ }
+}
diff --git a/src/bignum.hpp b/src/bignum.hpp
index 6fb22c5a1d..57ae4ab688 100644
--- a/src/bignum.hpp
+++ b/src/bignum.hpp
@@ -32,6 +32,11 @@ void bignum_init_bignum(BigNum *dest, BigNum *src);
bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed);
uint64_t bignum_to_twos_complement(BigNum *bn);
+void bignum_write_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian);
+void bignum_write_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian);
+void bignum_read_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian, bool is_signed);
+void bignum_read_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian);
+
// returns true if overflow happened
bool bignum_add(BigNum *dest, BigNum *op1, BigNum *op2);
bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 0e5b8a5ea1..3a1fad3958 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1693,6 +1693,14 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
}
+static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
+ IrInstructionBitCast *instruction)
+{
+ TypeTableEntry *wanted_type = instruction->base.value.type;
+ LLVMValueRef value = ir_llvm_value(g, instruction->value);
+ return LLVMBuildBitCast(g->builder, value, wanted_type->type_ref, "");
+}
+
static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
IrInstructionWidenOrShorten *instruction)
{
@@ -3180,6 +3188,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
case IrInstructionIdPtrCast:
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
+ case IrInstructionIdBitCast:
+ return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
case IrInstructionIdWidenOrShorten:
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
case IrInstructionIdPtrToInt:
@@ -4514,6 +4524,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2);
+ create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);
create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1);
create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
diff --git a/src/ir.cpp b/src/ir.cpp
index bda6852fdf..2f5ee84e2c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -469,6 +469,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
return IrInstructionIdPtrCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
+ return IrInstructionIdBitCast;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
return IrInstructionIdWidenOrShorten;
}
@@ -1922,6 +1926,20 @@ static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
+static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *dest_type, IrInstruction *value)
+{
+ IrInstructionBitCast *instruction = ir_build_instruction<IrInstructionBitCast>(
+ irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->value = value;
+
+ if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *target)
{
@@ -2704,6 +2722,16 @@ static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instr
}
}
+static IrInstruction *ir_instruction_bitcast_get_dep(IrInstructionBitCast *instruction,
+ size_t index)
+{
+ switch (index) {
+ case 0: return instruction->value;
+ case 1: return instruction->dest_type;
+ default: return nullptr;
+ }
+}
+
static IrInstruction *ir_instruction_widenorshorten_get_dep(IrInstructionWidenOrShorten *instruction, size_t index) {
switch (index) {
case 0: return instruction->target;
@@ -3000,6 +3028,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index);
case IrInstructionIdPtrCast:
return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index);
+ case IrInstructionIdBitCast:
+ return ir_instruction_bitcast_get_dep((IrInstructionBitCast *) instruction, index);
case IrInstructionIdWidenOrShorten:
return ir_instruction_widenorshorten_get_dep((IrInstructionWidenOrShorten *) instruction, index);
case IrInstructionIdIntToPtr:
@@ -4301,6 +4331,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value);
}
+ case BuiltinFnIdBitCast:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
+ if (arg0_value == irb->codegen->invalid_instruction)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
+ if (arg1_value == irb->codegen->invalid_instruction)
+ return arg1_value;
+
+ return ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value);
+ }
case BuiltinFnIdIntToPtr:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -13427,6 +13471,222 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc
return dest_type;
}
+static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
+ assert(val->special == ConstValSpecialStatic);
+ switch (val->type->id) {
+ case TypeTableEntryIdInvalid:
+ case TypeTableEntryIdVar:
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdOpaque:
+ case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdBlock:
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNullLit:
+ zig_unreachable();
+ case TypeTableEntryIdVoid:
+ return;
+ case TypeTableEntryIdBool:
+ buf[0] = val->data.x_bool ? 1 : 0;
+ return;
+ case TypeTableEntryIdInt:
+ bignum_write_twos_complement(&val->data.x_bignum, buf, val->type->data.integral.bit_count, codegen->is_big_endian);
+ return;
+ case TypeTableEntryIdFloat:
+ bignum_write_ieee597(&val->data.x_bignum, buf, val->type->data.floating.bit_count, codegen->is_big_endian);
+ return;
+ case TypeTableEntryIdPointer:
+ if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
+ BigNum bn;
+ bignum_init_unsigned(&bn, val->data.x_ptr.data.hard_coded_addr.addr);
+ bignum_write_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian);
+ return;
+ } else {
+ zig_unreachable();
+ }
+ case TypeTableEntryIdArray:
+ zig_panic("TODO buf_write_value_bytes array type");
+ case TypeTableEntryIdStruct:
+ zig_panic("TODO buf_write_value_bytes struct type");
+ case TypeTableEntryIdMaybe:
+ zig_panic("TODO buf_write_value_bytes maybe type");
+ case TypeTableEntryIdErrorUnion:
+ zig_panic("TODO buf_write_value_bytes error union");
+ case TypeTableEntryIdPureError:
+ zig_panic("TODO buf_write_value_bytes pure error type");
+ case TypeTableEntryIdEnum:
+ zig_panic("TODO buf_write_value_bytes enum type");
+ case TypeTableEntryIdEnumTag:
+ zig_panic("TODO buf_write_value_bytes enum tag type");
+ case TypeTableEntryIdFn:
+ zig_panic("TODO buf_write_value_bytes fn type");
+ case TypeTableEntryIdUnion:
+ zig_panic("TODO buf_write_value_bytes union type");
+ }
+ zig_unreachable();
+}
+
+static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
+ assert(val->special == ConstValSpecialStatic);
+ switch (val->type->id) {
+ case TypeTableEntryIdInvalid:
+ case TypeTableEntryIdVar:
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdOpaque:
+ case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdBlock:
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNullLit:
+ zig_unreachable();
+ case TypeTableEntryIdVoid:
+ return;
+ case TypeTableEntryIdBool:
+ val->data.x_bool = (buf[0] != 0);
+ return;
+ case TypeTableEntryIdInt:
+ bignum_read_twos_complement(&val->data.x_bignum, buf, val->type->data.integral.bit_count, codegen->is_big_endian,
+ val->type->data.integral.is_signed);
+ return;
+ case TypeTableEntryIdFloat:
+ bignum_read_ieee597(&val->data.x_bignum, buf, val->type->data.floating.bit_count, codegen->is_big_endian);
+ return;
+ case TypeTableEntryIdPointer:
+ {
+ val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ BigNum bn;
+ bignum_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian, false);
+ val->data.x_ptr.data.hard_coded_addr.addr = bignum_to_twos_complement(&bn);
+ return;
+ }
+ case TypeTableEntryIdArray:
+ zig_panic("TODO buf_read_value_bytes array type");
+ case TypeTableEntryIdStruct:
+ zig_panic("TODO buf_read_value_bytes struct type");
+ case TypeTableEntryIdMaybe:
+ zig_panic("TODO buf_read_value_bytes maybe type");
+ case TypeTableEntryIdErrorUnion:
+ zig_panic("TODO buf_read_value_bytes error union");
+ case TypeTableEntryIdPureError:
+ zig_panic("TODO buf_read_value_bytes pure error type");
+ case TypeTableEntryIdEnum:
+ zig_panic("TODO buf_read_value_bytes enum type");
+ case TypeTableEntryIdEnumTag:
+ zig_panic("TODO buf_read_value_bytes enum tag type");
+ case TypeTableEntryIdFn:
+ zig_panic("TODO buf_read_value_bytes fn type");
+ case TypeTableEntryIdUnion:
+ zig_panic("TODO buf_read_value_bytes union type");
+ }
+ zig_unreachable();
+}
+
+static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
+ IrInstruction *dest_type_value = instruction->dest_type->other;
+ TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *value = instruction->value->other;
+ TypeTableEntry *src_type = value->value.type;
+ if (type_is_invalid(src_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ ensure_complete_type(ira->codegen, dest_type);
+ ensure_complete_type(ira->codegen, src_type);
+
+ if (type_is_codegen_pointer(src_type)) {
+ ir_add_error(ira, value,
+ buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ switch (src_type->id) {
+ case TypeTableEntryIdInvalid:
+ case TypeTableEntryIdVar:
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdOpaque:
+ case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdBlock:
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNullLit:
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ default:
+ break;
+ }
+
+ if (type_is_codegen_pointer(dest_type)) {
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ switch (dest_type->id) {
+ case TypeTableEntryIdInvalid:
+ case TypeTableEntryIdVar:
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdOpaque:
+ case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdBlock:
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNullLit:
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ default:
+ break;
+ }
+
+ uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
+ uint64_t src_size_bytes = type_size(ira->codegen, src_type);
+ if (dest_size_bytes != src_size_bytes) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
+ buf_ptr(&dest_type->name), dest_size_bytes,
+ buf_ptr(&src_type->name), src_size_bytes));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ if (instr_is_comptime(value)) {
+ ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+ if (!val)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ out_val->type = dest_type;
+ uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
+ buf_write_value_bytes(ira->codegen, buf, val);
+ buf_read_value_bytes(ira->codegen, buf, out_val);
+ return dest_type;
+ }
+
+ IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr, value);
+ ir_link_new_instruction(result, &instruction->base);
+ result->value.type = dest_type;
+ return dest_type;
+}
+
static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
IrInstruction *dest_type_value = instruction->dest_type->other;
TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value);
@@ -13697,6 +13957,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
case IrInstructionIdPtrCast:
return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);
+ case IrInstructionIdBitCast:
+ return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
case IrInstructionIdIntToPtr:
return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction);
case IrInstructionIdEnumTagName:
@@ -13872,6 +14134,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTestComptime:
case IrInstructionIdInitEnum:
case IrInstructionIdPtrCast:
+ case IrInstructionIdBitCast:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
case IrInstructionIdIntToPtr:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 05d8a780cf..f7e0af0713 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -756,7 +756,7 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction)
}
static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
- fprintf(irp->f, "@ptrcast(");
+ fprintf(irp->f, "@ptrCast(");
if (instruction->dest_type) {
ir_print_other_instruction(irp, instruction->dest_type);
}
@@ -765,6 +765,16 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
+ fprintf(irp->f, "@bitCast(");
+ if (instruction->dest_type) {
+ ir_print_other_instruction(irp, instruction->dest_type);
+ }
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->value);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
fprintf(irp->f, "@widenOrShorten(");
ir_print_other_instruction(irp, instruction->target);
@@ -1124,6 +1134,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdPtrCast:
ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
break;
+ case IrInstructionIdBitCast:
+ ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
+ break;
case IrInstructionIdWidenOrShorten:
ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
break;