diff --git a/doc/langref.html.in b/doc/langref.html.in index 3a3eaf708c..9a286cb063 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7823,7 +7823,7 @@ Environments: coreclr opencl
- The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem
+ The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system
abstractions, and thus takes additional work to support more platforms.
Not all standard library code requires operating system abstractions, however,
so things such as generic data structures work an all above platforms.
diff --git a/src/all_types.hpp b/src/all_types.hpp
index fe36eb3a5d..29598672cd 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2198,6 +2198,7 @@ enum IrInstructionId {
IrInstructionIdPtrCastSrc,
IrInstructionIdPtrCastGen,
IrInstructionIdBitCast,
+ IrInstructionIdBitCastGen,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
IrInstructionIdPtrToInt,
@@ -3055,6 +3056,13 @@ struct IrInstructionBitCast {
IrInstruction *value;
};
+struct IrInstructionBitCastGen {
+ IrInstruction base;
+
+ IrInstruction *operand;
+ LLVMValueRef tmp_ptr;
+};
+
struct IrInstructionWidenOrShorten {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 6c9e8ccc4b..c43611e8af 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3073,14 +3073,32 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
}
static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
- IrInstructionBitCast *instruction)
+ IrInstructionBitCastGen *instruction)
{
ZigType *wanted_type = instruction->base.value.type;
- LLVMValueRef value = ir_llvm_value(g, instruction->value);
- // We either bitcast the value directly or bitcast the pointer which does a pointer cast
- LLVMTypeRef wanted_type_ref = handle_is_ptr(wanted_type) ?
- LLVMPointerType(wanted_type->type_ref, 0) : wanted_type->type_ref;
- return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
+ ZigType *actual_type = instruction->operand->value.type;
+ LLVMValueRef value = ir_llvm_value(g, instruction->operand);
+
+ bool wanted_is_ptr = handle_is_ptr(wanted_type);
+ bool actual_is_ptr = handle_is_ptr(actual_type);
+ if (wanted_is_ptr == actual_is_ptr) {
+ // We either bitcast the value directly or bitcast the pointer which does a pointer cast
+ LLVMTypeRef wanted_type_ref = wanted_is_ptr ?
+ LLVMPointerType(wanted_type->type_ref, 0) : wanted_type->type_ref;
+ return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
+ } else if (actual_is_ptr) {
+ LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(wanted_type->type_ref, 0);
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
+ uint32_t alignment = get_abi_alignment(g, actual_type);
+ return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
+ } else {
+ assert(instruction->tmp_ptr != nullptr);
+ LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(actual_type->type_ref, 0);
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, "");
+ uint32_t alignment = get_abi_alignment(g, wanted_type);
+ gen_store_untyped(g, value, bitcasted_ptr, alignment, false);
+ return instruction->tmp_ptr;
+ }
}
static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
@@ -5469,6 +5487,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPtrCastSrc:
case IrInstructionIdCmpxchgSrc:
case IrInstructionIdLoadPtr:
+ case IrInstructionIdBitCast:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5565,8 +5584,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
case IrInstructionIdPtrCastGen:
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
- case IrInstructionIdBitCast:
- return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
+ case IrInstructionIdBitCastGen:
+ return ir_render_bit_cast(g, executable, (IrInstructionBitCastGen *)instruction);
case IrInstructionIdWidenOrShorten:
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
case IrInstructionIdPtrToInt:
@@ -6764,6 +6783,9 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdLoadPtrGen) {
IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction;
slot = &load_ptr_inst->tmp_ptr;
+ } else if (instruction->id == IrInstructionIdBitCastGen) {
+ IrInstructionBitCastGen *bit_cast_inst = (IrInstructionBitCastGen *)instruction;
+ slot = &bit_cast_inst->tmp_ptr;
} else if (instruction->id == IrInstructionIdVectorToArray) {
IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
diff --git a/src/ir.cpp b/src/ir.cpp
index 5fae81f0ce..36f11cb108 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -744,6 +744,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
return IrInstructionIdBitCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
+ return IrInstructionIdBitCastGen;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
return IrInstructionIdWidenOrShorten;
}
@@ -2317,12 +2321,25 @@ static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *s
instruction->dest_type = dest_type;
instruction->value = value;
- if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(dest_type, irb->current_basic_block);
ir_ref_instruction(value, irb->current_basic_block);
return &instruction->base;
}
+static IrInstruction *ir_build_bit_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *operand, ZigType *ty)
+{
+ IrInstructionBitCastGen *instruction = ir_build_instruction