From 5e1003bc81466b8ca0e3a3adb613bac8f34f2712 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 1 May 2019 01:56:06 -0400
Subject: no-copy semantics for basic runtime function call variable init
```zig
export fn entry() void {
var x: Foo = foo();
}
```
```llvm
define void @entry() #2 !dbg !37 {
Entry:
%x = alloca %Foo, align 4
call fastcc void @foo(%Foo* sret %x), !dbg !48
call void @llvm.dbg.declare(metadata %Foo* %x, metadata !41, metadata !DIExpression()), !dbg !49
ret void, !dbg !50
}
```
---
src/codegen.cpp | 90 ++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 54 insertions(+), 36 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 826a9463ac..2cb3584e68 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1982,6 +1982,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
}
static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {
+ if (g->strip_debug_symbols) return;
assert(var->di_loc_var != nullptr);
AstNode *source_node = var->decl_node;
ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1,
@@ -2288,7 +2289,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
return;
}
if (fn_walk->id == FnWalkIdCall) {
- IrInstructionCall *instruction = fn_walk->data.call.inst;
+ IrInstructionCallGen *instruction = fn_walk->data.call.inst;
bool is_var_args = fn_walk->data.call.is_var_args;
for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
IrInstruction *param_instruction = instruction->args[call_i];
@@ -3328,10 +3329,8 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
}
-static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
- IrInstructionDeclVarGen *decl_var_instruction)
-{
- ZigVar *var = decl_var_instruction->var;
+static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) {
+ ZigVar *var = instruction->var;
if (!type_has_bits(var->var_type))
return nullptr;
@@ -3339,20 +3338,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
return nullptr;
- IrInstruction *init_value = decl_var_instruction->init_value;
-
- bool have_init_expr = !value_is_all_undef(&init_value->value);
-
- if (have_init_expr) {
- ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
- PtrLenSingle, var->align_bytes, 0, 0, false);
- LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
- gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
- } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
- uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
- gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
- }
-
+ var->value_ref = ir_llvm_value(g, instruction->var_ptr);
gen_var_debug_decl(g, var);
return nullptr;
}
@@ -3568,6 +3554,13 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
}
}
+static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,
+ IrInstructionReturnPtr *instruction)
+{
+ assert(g->cur_ret_ptr != nullptr || !type_has_bits(instruction->base.value.type));
+ return g->cur_ret_ptr;
+}
+
static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);
ZigType *array_ptr_type = instruction->array_ptr->value.type;
@@ -3719,7 +3712,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);
}
-static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
+static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) {
LLVMValueRef fn_val;
ZigType *fn_type;
if (instruction->fn_entry) {
@@ -3742,8 +3735,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
bool is_var_args = fn_type_id->is_var_args;
ZigList gen_param_values = {};
+ LLVMValueRef result_loc = first_arg_ret ? ir_llvm_value(g, instruction->result_loc) : nullptr;
if (first_arg_ret) {
- gen_param_values.append(instruction->tmp_ptr);
+ gen_param_values.append(result_loc);
}
if (prefix_arg_err_ret_stack) {
gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
@@ -3751,7 +3745,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
if (instruction->is_async) {
gen_param_values.append(ir_llvm_value(g, instruction->async_allocator));
- LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
+ LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
gen_param_values.append(err_val_ptr);
}
FnWalk fn_walk = {};
@@ -3794,9 +3788,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
if (instruction->is_async) {
- LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
+ LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
LLVMBuildStore(g->builder, result, payload_ptr);
- return instruction->tmp_ptr;
+ return result_loc;
}
if (src_return_type->id == ZigTypeIdUnreachable) {
@@ -3805,11 +3799,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
return nullptr;
} else if (first_arg_ret) {
set_call_instr_sret(g, result);
- return instruction->tmp_ptr;
+ return result_loc;
} else if (handle_is_ptr(src_return_type)) {
- auto store_instr = LLVMBuildStore(g->builder, result, instruction->tmp_ptr);
- LLVMSetAlignment(store_instr, LLVMGetAlignment(instruction->tmp_ptr));
- return instruction->tmp_ptr;
+ LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
+ LLVMSetAlignment(store_instr, LLVMGetAlignment(result_loc));
+ return result_loc;
} else {
return result;
}
@@ -5535,7 +5529,9 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
}
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
- set_debug_location(g, instruction);
+ if (!g->strip_debug_symbols) {
+ set_debug_location(g, instruction);
+ }
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -5608,8 +5604,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdGlobalAsm:
case IrInstructionIdHasDecl:
case IrInstructionIdUndeclaredIdent:
+ case IrInstructionIdCallSrc:
+ case IrInstructionIdAllocaSrc:
zig_unreachable();
+ case IrInstructionIdAllocaGen:
+ return nullptr;
+
case IrInstructionIdDeclVarGen:
return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
case IrInstructionIdReturn:
@@ -5632,10 +5633,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
case IrInstructionIdVarPtr:
return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
+ case IrInstructionIdReturnPtr:
+ return ir_render_return_ptr(g, executable, (IrInstructionReturnPtr *)instruction);
case IrInstructionIdElemPtr:
return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);
- case IrInstructionIdCall:
- return ir_render_call(g, executable, (IrInstructionCall *)instruction);
+ case IrInstructionIdCallGen:
+ return ir_render_call(g, executable, (IrInstructionCallGen *)instruction);
case IrInstructionIdStructFieldPtr:
return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
case IrInstructionIdUnionFieldPtr:
@@ -6851,6 +6854,26 @@ static void do_code_gen(CodeGen *g) {
}
// allocate temporary stack data
+ for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
+ IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
+ ZigType *ptr_type = instruction->base.value.type;
+ assert(ptr_type->id == ZigTypeIdPointer);
+ ZigType *child_type = ptr_type->data.pointer.child_type;
+ if (!type_has_bits(child_type))
+ continue;
+ if (instruction->base.ref_count == 0)
+ continue;
+ if (instruction->base.value.special != ConstValSpecialRuntime) {
+ if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
+ ConstValSpecialRuntime)
+ {
+ continue;
+ }
+ }
+ instruction->base.llvm_value = build_alloca(g, child_type, instruction->name_hint,
+ get_ptr_align(g, ptr_type));
+ }
+
for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {
IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
LLVMValueRef *slot;
@@ -6873,9 +6896,6 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdUnionInit) {
IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
slot = &union_init_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdCall) {
- IrInstructionCall *call_instruction = (IrInstructionCall *)instruction;
- slot = &call_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdSlice) {
IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
slot = &slice_instruction->tmp_ptr;
@@ -6939,8 +6959,6 @@ static void do_code_gen(CodeGen *g) {
}
if (var->src_arg_index == SIZE_MAX) {
- var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
-
var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1),
get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
--
cgit v1.2.3
From a4aca787229e3b0b3dc992b747cc72a561c2078c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 30 May 2019 17:05:06 -0400
Subject: no-copy semantics for if expr
```zig
export fn entry() void {
var c = true;
var x = if (c) u8(4) else u32(10);
}
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%c = alloca i1, align 1
%x = alloca i32, align 4
store i1 true, i1* %c, align 1, !dbg !44
call void @llvm.dbg.declare(metadata i1* %c, metadata !39, metadata !DIExpression()), !dbg !45
%0 = load i1, i1* %c, align 1, !dbg !46
br i1 %0, label %Then, label %Else, !dbg !46
Then: ; preds = %Entry
br label %EndIf, !dbg !47
Else: ; preds = %Entry
br label %EndIf, !dbg !47
EndIf: ; preds = %Else, %Then
%1 = phi i32 [ 4, %Then ], [ 10, %Else ], !dbg !47
store i32 %1, i32* %x, align 4, !dbg !47
call void @llvm.dbg.declare(metadata i32* %x, metadata !42, metadata !DIExpression()), !dbg !48
ret void, !dbg !49
}
```
---
BRANCH_TODO | 18 ++
src/all_types.hpp | 43 ++++-
src/codegen.cpp | 5 +-
src/ir.cpp | 483 +++++++++++++++++++++++++++++++++++-------------------
src/ir_print.cpp | 27 +++
5 files changed, 404 insertions(+), 172 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 294d3e677f..ffcf35d810 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -8,3 +8,21 @@ migrate all the alloca_list to alloca_gen_list
migrate ir_build_var_decl_src to use ir_build_alloca_src and explicitly initialize
inferred comptime
+
+
+ if (lval == LValNone) {
+ if (result_loc->id == ResultLocIdNone)
+ return value;
+ }
+
+ assert(lval == LValPtr);
+
+ // We needed a pointer to a value, but we got a value. So we create
+ // an instruction which just makes a pointer of it.
+ return ir_build_ref(irb, scope, value->source_node, value, false, false);
+
+handle if with no else
+
+handle comptime if condition
+
+handle mixed runtime and comptime peers
diff --git a/src/all_types.hpp b/src/all_types.hpp
index ae8d9c3fb8..79ad2f8958 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -42,6 +42,7 @@ struct Tld;
struct TldExport;
struct IrAnalyze;
struct ResultLoc;
+struct ResultLocPeer;
enum X64CABIClass {
X64CABIClass_Unknown,
@@ -2127,6 +2128,8 @@ struct IrBasicBlock {
const char *name_hint;
size_t debug_id;
size_t ref_count;
+ // index into the basic block list
+ size_t index;
LLVMBasicBlockRef llvm_block;
LLVMBasicBlockRef llvm_exit_block;
// The instruction that referenced this basic block and caused us to
@@ -2315,10 +2318,14 @@ enum IrInstructionId {
IrInstructionIdUndeclaredIdent,
IrInstructionIdAllocaSrc,
IrInstructionIdAllocaGen,
+ IrInstructionIdEndExpr,
};
struct IrInstruction {
IrInstructionId id;
+ // true if this instruction was generated by zig and not from user code
+ bool is_gen;
+
Scope *scope;
AstNode *source_node;
ConstExprValue value;
@@ -2332,8 +2339,6 @@ struct IrInstruction {
// with this child field.
IrInstruction *child;
IrBasicBlock *owner_bb;
- // true if this instruction was generated by zig and not from user code
- bool is_gen;
};
struct IrInstructionDeclVarSrc {
@@ -3571,16 +3576,28 @@ struct IrInstructionAllocaGen {
const char *name_hint;
};
+struct IrInstructionEndExpr {
+ IrInstruction base;
+
+ IrInstruction *value;
+ ResultLoc *result_loc;
+ LVal lval;
+};
+
enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
ResultLocIdVar,
ResultLocIdReturn,
+ ResultLocIdPeer,
+ ResultLocIdPeerParent,
};
struct ResultLoc {
ResultLocId id;
IrInstruction *source_instruction;
+ IrInstruction *gen_instruction;
+ ZigType *implicit_elem_type;
};
struct ResultLocNone {
@@ -3597,6 +3614,28 @@ struct ResultLocReturn {
ResultLoc base;
};
+struct ResultLocPeerParent {
+ ResultLoc base;
+
+ ResultLoc *parent;
+ ResultLocPeer *peers;
+ size_t peer_count;
+ ZigType *resolved_type;
+};
+
+struct IrSuspendPosition {
+ size_t basic_block_index;
+ size_t instruction_index;
+};
+
+struct ResultLocPeer {
+ ResultLoc base;
+
+ ResultLocPeerParent *parent;
+ IrBasicBlock *next_bb;
+ IrSuspendPosition suspend_pos;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2cb3584e68..ccbf911686 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5606,10 +5606,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdUndeclaredIdent:
case IrInstructionIdCallSrc:
case IrInstructionIdAllocaSrc:
- zig_unreachable();
-
+ case IrInstructionIdEndExpr:
case IrInstructionIdAllocaGen:
- return nullptr;
+ zig_unreachable();
case IrInstructionIdDeclVarGen:
return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
diff --git a/src/ir.cpp b/src/ir.cpp
index 5b6ce22620..c406a809ca 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -38,6 +38,7 @@ struct IrAnalyze {
ZigType *explicit_return_type;
AstNode *explicit_return_type_source_node;
ZigList src_implicit_return_type_list;
+ ZigList resume_stack;
IrBasicBlock *const_predecessor_bb;
};
@@ -159,7 +160,6 @@ enum UndefAllowed {
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
ResultLoc *result_loc);
-static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);
static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
@@ -167,7 +167,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);
static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
-static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
+static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc);
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
@@ -184,6 +184,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
ZigType *ptr_type);
static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *dest_type);
+static IrInstruction *ir_resolve_result_runtime(IrAnalyze *ira, ResultLoc *result_loc, ZigType *elem_type);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -387,6 +388,7 @@ static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const c
result->scope = scope;
result->name_hint = name_hint;
result->debug_id = exec_next_debug_id(irb->exec);
+ result->index = SIZE_MAX; // set later
return result;
}
@@ -1036,6 +1038,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaGen *) {
return IrInstructionIdAllocaGen;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) {
+ return IrInstructionIdEndExpr;
+}
+
template
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate(1);
@@ -1373,10 +1379,11 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
static IrInstruction *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
FnInline fn_inline, bool is_async, IrInstruction *async_allocator, IrInstruction *new_stack,
- IrInstruction *result_loc)
+ ResultLoc *result_loc, ZigType *return_type)
{
IrInstructionCallGen *call_instruction = ir_build_instruction(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
+ call_instruction->base.value.type = return_type;
call_instruction->fn_entry = fn_entry;
call_instruction->fn_ref = fn_ref;
call_instruction->fn_inline = fn_inline;
@@ -1385,14 +1392,14 @@ static IrInstruction *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_in
call_instruction->is_async = is_async;
call_instruction->async_allocator = async_allocator;
call_instruction->new_stack = new_stack;
- call_instruction->result_loc = result_loc;
+ call_instruction->result_loc = ir_resolve_result_runtime(ira, result_loc, return_type);
if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ira->new_irb.current_basic_block);
for (size_t i = 0; i < arg_count; i += 1)
ir_ref_instruction(args[i], ira->new_irb.current_basic_block);
if (async_allocator != nullptr) ir_ref_instruction(async_allocator, ira->new_irb.current_basic_block);
if (new_stack != nullptr) ir_ref_instruction(new_stack, ira->new_irb.current_basic_block);
- if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+ if (call_instruction->result_loc != nullptr) ir_ref_instruction(call_instruction->result_loc, ira->new_irb.current_basic_block);
return &call_instruction->base;
}
@@ -3187,6 +3194,19 @@ static IrInstructionAllocaGen *ir_create_alloca_gen(IrAnalyze *ira, IrInstructio
return instruction;
}
+static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *value, LVal lval, ResultLoc *result_loc)
+{
+ IrInstructionEndExpr *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->value = value;
+ instruction->lval = lval;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -3287,6 +3307,7 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
}
static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *basic_block) {
+ basic_block->index = irb->exec->basic_block_list.length;
irb->exec->basic_block_list.append(basic_block);
ir_set_cursor_at_end(irb, basic_block);
}
@@ -3623,6 +3644,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
// keep the last noreturn statement value around in case we need to return it
noreturn_return_value = statement_value;
}
+ // This logic must be kept in sync with
+ // [STMT_EXPR_TEST_THING] <--- (search this token)
if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_instruction) {
// defer starts a new scope
child_scope = statement_node->data.defer.child_scope;
@@ -4164,7 +4187,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg;
IrInstruction *type_of = ir_build_typeof(irb, scope, node, arg);
- return ir_lval_wrap(irb, scope, type_of, lval);
+ return ir_lval_wrap(irb, scope, type_of, lval, result_loc);
}
case BuiltinFnIdSetCold:
{
@@ -4174,7 +4197,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_cold = ir_build_set_cold(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_cold, lval);
+ return ir_lval_wrap(irb, scope, set_cold, lval, result_loc);
}
case BuiltinFnIdSetRuntimeSafety:
{
@@ -4184,7 +4207,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_safety, lval);
+ return ir_lval_wrap(irb, scope, set_safety, lval, result_loc);
}
case BuiltinFnIdSetFloatMode:
{
@@ -4194,7 +4217,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_float_mode, lval);
+ return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc);
}
case BuiltinFnIdSizeof:
{
@@ -4204,7 +4227,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, size_of, lval);
+ return ir_lval_wrap(irb, scope, size_of, lval, result_loc);
}
case BuiltinFnIdImport:
{
@@ -4214,12 +4237,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *import = ir_build_import(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, import, lval);
+ return ir_lval_wrap(irb, scope, import, lval, result_loc);
}
case BuiltinFnIdCImport:
{
IrInstruction *c_import = ir_build_c_import(irb, scope, node);
- return ir_lval_wrap(irb, scope, c_import, lval);
+ return ir_lval_wrap(irb, scope, c_import, lval, result_loc);
}
case BuiltinFnIdCInclude:
{
@@ -4234,7 +4257,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *c_include = ir_build_c_include(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, c_include, lval);
+ return ir_lval_wrap(irb, scope, c_include, lval, result_loc);
}
case BuiltinFnIdCDefine:
{
@@ -4254,7 +4277,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, c_define, lval);
+ return ir_lval_wrap(irb, scope, c_define, lval, result_loc);
}
case BuiltinFnIdCUndef:
{
@@ -4269,7 +4292,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *c_undef = ir_build_c_undef(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, c_undef, lval);
+ return ir_lval_wrap(irb, scope, c_undef, lval, result_loc);
}
case BuiltinFnIdCompileErr:
{
@@ -4279,7 +4302,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *compile_err = ir_build_compile_err(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, compile_err, lval);
+ return ir_lval_wrap(irb, scope, compile_err, lval, result_loc);
}
case BuiltinFnIdCompileLog:
{
@@ -4293,7 +4316,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
IrInstruction *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args);
- return ir_lval_wrap(irb, scope, compile_log, lval);
+ return ir_lval_wrap(irb, scope, compile_log, lval, result_loc);
}
case BuiltinFnIdErrName:
{
@@ -4303,7 +4326,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *err_name = ir_build_err_name(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, err_name, lval);
+ return ir_lval_wrap(irb, scope, err_name, lval, result_loc);
}
case BuiltinFnIdEmbedFile:
{
@@ -4313,7 +4336,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *embed_file = ir_build_embed_file(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, embed_file, lval);
+ return ir_lval_wrap(irb, scope, embed_file, lval, result_loc);
}
case BuiltinFnIdCmpxchgWeak:
case BuiltinFnIdCmpxchgStrong:
@@ -4350,7 +4373,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
- return ir_lval_wrap(irb, scope, cmpxchg, lval);
+ return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc);
}
case BuiltinFnIdFence:
{
@@ -4360,7 +4383,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *fence = ir_build_fence(irb, scope, node, arg0_value, AtomicOrderUnordered);
- return ir_lval_wrap(irb, scope, fence, lval);
+ return ir_lval_wrap(irb, scope, fence, lval, result_loc);
}
case BuiltinFnIdDivExact:
{
@@ -4375,7 +4398,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdDivTrunc:
{
@@ -4390,7 +4413,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdDivFloor:
{
@@ -4405,7 +4428,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdRem:
{
@@ -4420,7 +4443,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdMod:
{
@@ -4435,7 +4458,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdSqrt:
{
@@ -4450,7 +4473,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *ir_sqrt = ir_build_sqrt(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, ir_sqrt, lval);
+ return ir_lval_wrap(irb, scope, ir_sqrt, lval, result_loc);
}
case BuiltinFnIdTruncate:
{
@@ -4465,7 +4488,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, truncate, lval);
+ return ir_lval_wrap(irb, scope, truncate, lval, result_loc);
}
case BuiltinFnIdIntCast:
{
@@ -4480,7 +4503,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdFloatCast:
{
@@ -4495,7 +4518,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdErrSetCast:
{
@@ -4510,7 +4533,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdFromBytes:
{
@@ -4525,7 +4548,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdToBytes:
{
@@ -4535,7 +4558,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntToFloat:
{
@@ -4550,7 +4573,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdFloatToInt:
{
@@ -4565,7 +4588,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdErrToInt:
{
@@ -4575,7 +4598,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntToErr:
{
@@ -4585,7 +4608,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdBoolToInt:
{
@@ -4595,7 +4618,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntType:
{
@@ -4610,7 +4633,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, int_type, lval);
+ return ir_lval_wrap(irb, scope, int_type, lval, result_loc);
}
case BuiltinFnIdVectorType:
{
@@ -4625,7 +4648,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, vector_type, lval);
+ return ir_lval_wrap(irb, scope, vector_type, lval, result_loc);
}
case BuiltinFnIdMemcpy:
{
@@ -4645,7 +4668,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *ir_memcpy = ir_build_memcpy(irb, scope, node, arg0_value, arg1_value, arg2_value);
- return ir_lval_wrap(irb, scope, ir_memcpy, lval);
+ return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc);
}
case BuiltinFnIdMemset:
{
@@ -4665,7 +4688,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *ir_memset = ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);
- return ir_lval_wrap(irb, scope, ir_memset, lval);
+ return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc);
}
case BuiltinFnIdMemberCount:
{
@@ -4675,7 +4698,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *member_count = ir_build_member_count(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, member_count, lval);
+ return ir_lval_wrap(irb, scope, member_count, lval, result_loc);
}
case BuiltinFnIdMemberType:
{
@@ -4691,7 +4714,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, member_type, lval);
+ return ir_lval_wrap(irb, scope, member_type, lval, result_loc);
}
case BuiltinFnIdMemberName:
{
@@ -4707,7 +4730,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, member_name, lval);
+ return ir_lval_wrap(irb, scope, member_name, lval, result_loc);
}
case BuiltinFnIdField:
{
@@ -4736,14 +4759,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_info, lval);
+ return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
}
case BuiltinFnIdBreakpoint:
- return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);
case BuiltinFnIdReturnAddress:
- return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc);
case BuiltinFnIdFrameAddress:
- return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc);
case BuiltinFnIdHandle:
if (!irb->exec->fn_entry) {
add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));
@@ -4753,7 +4776,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));
return irb->codegen->invalid_instruction;
}
- return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc);
case BuiltinFnIdAlignOf:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -4762,16 +4785,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *align_of = ir_build_align_of(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, align_of, lval);
+ return ir_lval_wrap(irb, scope, align_of, lval, result_loc);
}
case BuiltinFnIdAddWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc);
case BuiltinFnIdSubWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc);
case BuiltinFnIdMulWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc);
case BuiltinFnIdShlWithOverflow:
- return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc);
case BuiltinFnIdTypeName:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -4780,7 +4803,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *type_name = ir_build_type_name(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_name, lval);
+ return ir_lval_wrap(irb, scope, type_name, lval, result_loc);
}
case BuiltinFnIdPanic:
{
@@ -4790,7 +4813,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *panic = ir_build_panic(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, panic, lval);
+ return ir_lval_wrap(irb, scope, panic, lval, result_loc);
}
case BuiltinFnIdPtrCast:
{
@@ -4805,7 +4828,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, ptr_cast, lval);
+ return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc);
}
case BuiltinFnIdBitCast:
{
@@ -4820,7 +4843,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bit_cast = ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, bit_cast, lval);
+ return ir_lval_wrap(irb, scope, bit_cast, lval, result_loc);
}
case BuiltinFnIdIntToPtr:
{
@@ -4835,7 +4858,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *int_to_ptr = ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, int_to_ptr, lval);
+ return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc);
}
case BuiltinFnIdPtrToInt:
{
@@ -4845,7 +4868,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *ptr_to_int = ir_build_ptr_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, ptr_to_int, lval);
+ return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc);
}
case BuiltinFnIdTagName:
{
@@ -4856,7 +4879,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value);
IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag);
- return ir_lval_wrap(irb, scope, tag_name, lval);
+ return ir_lval_wrap(irb, scope, tag_name, lval, result_loc);
}
case BuiltinFnIdTagType:
{
@@ -4866,7 +4889,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *tag_type = ir_build_tag_type(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, tag_type, lval);
+ return ir_lval_wrap(irb, scope, tag_type, lval, result_loc);
}
case BuiltinFnIdFieldParentPtr:
{
@@ -4886,7 +4909,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *field_parent_ptr = ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr);
- return ir_lval_wrap(irb, scope, field_parent_ptr, lval);
+ return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc);
}
case BuiltinFnIdByteOffsetOf:
{
@@ -4901,7 +4924,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, offset_of, lval);
+ return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
}
case BuiltinFnIdBitOffsetOf:
{
@@ -4916,7 +4939,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, offset_of, lval);
+ return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
}
case BuiltinFnIdInlineCall:
case BuiltinFnIdNoInlineCall:
@@ -4944,7 +4967,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
fn_inline, false, nullptr, nullptr, result_loc);
- return ir_lval_wrap(irb, scope, call, lval);
+ return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
case BuiltinFnIdNewStackCall:
{
@@ -4975,7 +4998,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
FnInlineAuto, false, nullptr, new_stack, result_loc);
- return ir_lval_wrap(irb, scope, call, lval);
+ return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
case BuiltinFnIdTypeId:
{
@@ -4985,7 +5008,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *type_id = ir_build_type_id(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_id, lval);
+ return ir_lval_wrap(irb, scope, type_id, lval, result_loc);
}
case BuiltinFnIdShlExact:
{
@@ -5000,7 +5023,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdShrExact:
{
@@ -5015,7 +5038,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true);
- return ir_lval_wrap(irb, scope, bin_op, lval);
+ return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
}
case BuiltinFnIdSetEvalBranchQuota:
{
@@ -5025,7 +5048,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval);
+ return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc);
}
case BuiltinFnIdAlignCast:
{
@@ -5040,17 +5063,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *align_cast = ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, align_cast, lval);
+ return ir_lval_wrap(irb, scope, align_cast, lval, result_loc);
}
case BuiltinFnIdOpaqueType:
{
IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);
- return ir_lval_wrap(irb, scope, opaque_type, lval);
+ return ir_lval_wrap(irb, scope, opaque_type, lval, result_loc);
}
case BuiltinFnIdThis:
{
IrInstruction *this_inst = ir_gen_this(irb, scope, node);
- return ir_lval_wrap(irb, scope, this_inst, lval);
+ return ir_lval_wrap(irb, scope, this_inst, lval, result_loc);
}
case BuiltinFnIdSetAlignStack:
{
@@ -5060,7 +5083,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, set_align_stack, lval);
+ return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc);
}
case BuiltinFnIdArgType:
{
@@ -5075,7 +5098,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, arg_type, lval);
+ return ir_lval_wrap(irb, scope, arg_type, lval, result_loc);
}
case BuiltinFnIdExport:
{
@@ -5095,12 +5118,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg2_value;
IrInstruction *ir_export = ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value);
- return ir_lval_wrap(irb, scope, ir_export, lval);
+ return ir_lval_wrap(irb, scope, ir_export, lval, result_loc);
}
case BuiltinFnIdErrorReturnTrace:
{
IrInstruction *error_return_trace = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::Null);
- return ir_lval_wrap(irb, scope, error_return_trace, lval);
+ return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc);
}
case BuiltinFnIdAtomicRmw:
{
@@ -5168,7 +5191,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdEnumToInt:
{
@@ -5178,7 +5201,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg0_value;
IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdCtz:
case BuiltinFnIdPopCount:
@@ -5216,7 +5239,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
default:
zig_unreachable();
}
- return ir_lval_wrap(irb, scope, result, lval);
+ return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdHasDecl:
{
@@ -5231,7 +5254,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, has_decl, lval);
+ return ir_lval_wrap(irb, scope, has_decl, lval, result_loc);
}
}
zig_unreachable();
@@ -5271,10 +5294,12 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
is_async, async_allocator, nullptr, result_loc);
- return ir_lval_wrap(irb, scope, fn_call, lval);
+ return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
}
-static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeIfBoolExpr);
IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
@@ -5295,12 +5320,29 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "Else");
IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "EndIf");
- ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);
+ IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition,
+ then_block, else_block, is_comptime);
+
+ ResultLocPeerParent *peer_parent = allocate(1);
+ peer_parent->base.id = ResultLocIdPeerParent;
+ peer_parent->base.source_instruction = cond_br_inst;
+ peer_parent->parent = result_loc;
+ peer_parent->peer_count = 2;
+ peer_parent->peers = allocate(2);
+ peer_parent->peers[0].base.id = ResultLocIdPeer;
+ peer_parent->peers[0].base.source_instruction = cond_br_inst;
+ peer_parent->peers[0].parent = peer_parent;
+ peer_parent->peers[0].next_bb = else_block;
+ peer_parent->peers[1].base.id = ResultLocIdPeer;
+ peer_parent->peers[1].base.source_instruction = cond_br_inst;
+ peer_parent->peers[1].parent = peer_parent;
+ peer_parent->peers[1].next_bb = endif_block;
ir_set_cursor_at_end_and_append_block(irb, then_block);
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
- IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
+ IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval,
+ &peer_parent->peers[0].base);
if (then_expr_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -5310,7 +5352,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
ir_set_cursor_at_end_and_append_block(irb, else_block);
IrInstruction *else_expr_result;
if (else_node) {
- else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
+ else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);
if (else_expr_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
@@ -5328,7 +5370,8 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
incoming_blocks[0] = after_then_block;
incoming_blocks[1] = after_else_block;
- return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
+ return ir_lval_wrap(irb, scope, phi, lval, result_loc);
}
static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
@@ -5346,15 +5389,28 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone);
}
-static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval) {
- if (lval != LValPtr)
- return value;
- if (value == irb->codegen->invalid_instruction)
+static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval,
+ ResultLoc *result_loc)
+{
+ // This logic must be kept in sync with
+ // [STMT_EXPR_TEST_THING] <--- (search this token)
+ if (value == irb->codegen->invalid_instruction ||
+ instr_is_unreachable(value) ||
+ value->source_node->type == NodeTypeDefer ||
+ value->id == IrInstructionIdDeclVarSrc)
+ {
return value;
+ }
+
+ if (lval == LValPtr) {
+ // We needed a pointer to a value, but we got a value. So we create
+ // an instruction which just makes a pointer of it.
+ return ir_build_ref(irb, scope, value->source_node, value, false, false);
+ }
- // We needed a pointer to a value, but we got a value. So we create
- // an instruction which just makes a const pointer of it.
- return ir_build_ref(irb, scope, value->source_node, value, false, false);
+ // TODO remove the lval parameter here
+ ir_build_end_expr(irb, scope, value->source_node, value, lval, result_loc);
+ return value;
}
static PtrLen star_token_to_ptr_len(TokenId token_id) {
@@ -5455,7 +5511,9 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod
return ir_build_bool_not(irb, scope, node, value);
}
-static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypePrefixOpExpr);
PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
@@ -5464,18 +5522,18 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
case PrefixOpInvalid:
zig_unreachable();
case PrefixOpBoolNot:
- return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc);
case PrefixOpBinNot:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc);
case PrefixOpNegation:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc);
case PrefixOpNegationWrap:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc);
case PrefixOpOptional:
- return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc);
case PrefixOpAddrOf: {
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
- return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc);
}
}
zig_unreachable();
@@ -7677,33 +7735,33 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeTestDecl:
zig_unreachable();
case NodeTypeBlock:
- return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval, result_loc);
case NodeTypeGroupedExpr:
return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc);
case NodeTypeBinOpExpr:
- return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval, result_loc);
case NodeTypeIntLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc);
case NodeTypeFloatLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc);
case NodeTypeCharLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc);
case NodeTypeSymbol:
return ir_gen_symbol(irb, scope, node, lval);
case NodeTypeFnCallExpr:
return ir_gen_fn_call(irb, scope, node, lval, result_loc);
case NodeTypeIfBoolExpr:
- return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval);
+ return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc);
case NodeTypePrefixOpExpr:
- return ir_gen_prefix_op_expr(irb, scope, node, lval);
+ return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc);
case NodeTypeContainerInitExpr:
- return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval, result_loc);
case NodeTypeVariableDeclaration:
- return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc);
case NodeTypeWhileExpr:
- return ir_lval_wrap(irb, scope, ir_gen_while_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_while_expr(irb, scope, node), lval, result_loc);
case NodeTypeForExpr:
- return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval, result_loc);
case NodeTypeArrayAccessExpr:
return ir_gen_array_access(irb, scope, node, lval);
case NodeTypeReturnExpr:
@@ -7743,59 +7801,59 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
}
case NodeTypeBoolLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc);
case NodeTypeArrayType:
- return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc);
case NodeTypePointerType:
- return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc);
case NodeTypePromiseType:
- return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval, result_loc);
case NodeTypeStringLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc);
case NodeTypeUndefinedLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc);
case NodeTypeAsmExpr:
- return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc);
case NodeTypeNullLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc);
case NodeTypeIfErrorExpr:
- return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval, result_loc);
case NodeTypeIfOptional:
- return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval, result_loc);
case NodeTypeSwitchExpr:
- return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval, result_loc);
case NodeTypeCompTime:
return ir_gen_comptime(irb, scope, node, lval);
case NodeTypeErrorType:
- return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc);
case NodeTypeBreak:
- return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc);
case NodeTypeContinue:
- return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc);
case NodeTypeUnreachable:
- return ir_lval_wrap(irb, scope, ir_build_unreachable(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_build_unreachable(irb, scope, node), lval, result_loc);
case NodeTypeDefer:
- return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc);
case NodeTypeSliceExpr:
- return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval, result_loc);
case NodeTypeUnwrapErrorExpr:
- return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval, result_loc);
case NodeTypeContainerDecl:
- return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc);
case NodeTypeFnProto:
- return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc);
case NodeTypeErrorSetDecl:
- return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc);
case NodeTypeCancel:
- return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval, result_loc);
case NodeTypeResume:
- return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);
case NodeTypeAwaitExpr:
- return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval, result_loc);
case NodeTypeSuspend:
- return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc);
case NodeTypeEnumLiteral:
- return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc);
}
zig_unreachable();
}
@@ -10415,6 +10473,33 @@ static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *cons
ira->const_predecessor_bb = const_predecessor_bb;
}
+static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction, IrBasicBlock *next_bb,
+ IrSuspendPosition *suspend_pos)
+{
+ suspend_pos->basic_block_index = ira->old_bb_index;
+ suspend_pos->instruction_index = ira->instruction_index;
+
+ ira->old_bb_index = next_bb->index;
+ ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
+ assert(ira->old_irb.current_basic_block == next_bb);
+ ira->instruction_index = 0;
+ ira->const_predecessor_bb = nullptr;
+ next_bb->other = ir_get_new_bb_runtime(ira, next_bb, old_instruction);
+ ira->new_irb.current_basic_block = next_bb->other;
+ return ira->codegen->unreach_instruction;
+}
+
+static IrInstruction *ira_resume(IrAnalyze *ira) {
+ IrSuspendPosition pos = ira->resume_stack.pop();
+ ira->old_bb_index = pos.basic_block_index;
+ ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
+ ira->instruction_index = pos.instruction_index;
+ ira->const_predecessor_bb = nullptr;
+ ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->other;
+ assert(ira->new_irb.current_basic_block != nullptr);
+ return ira->codegen->unreach_instruction;
+}
+
static void ir_finish_bb(IrAnalyze *ira) {
ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
ira->instruction_index += 1;
@@ -10442,8 +10527,15 @@ static void ir_finish_bb(IrAnalyze *ira) {
ira->old_bb_index += 1;
continue;
}
- ira->new_irb.current_basic_block = old_bb->other;
+ // if there is a resume_stack, pop one from there rather than moving on.
+ // the last item of the resume stack will be a basic block that will
+ // move on to the next one below
+ if (ira->resume_stack.length != 0) {
+ ira_resume(ira);
+ return;
+ }
+ ira->new_irb.current_basic_block = old_bb->other;
ir_start_bb(ira, old_bb, nullptr);
return;
}
@@ -14232,9 +14324,26 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
return &result->base;
}
-static IrInstruction *ir_resolve_result_loc(IrAnalyze *ira, ResultLoc *result_loc, ZigType *elem_type) {
+static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_loc) {
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ case ResultLocIdPeerParent:
+ case ResultLocIdPeer:
+ zig_unreachable();
+ case ResultLocIdNone:
+ case ResultLocIdVar:
+ return nullptr;
+ case ResultLocIdReturn:
+ return ira->explicit_return_type;
+ }
+ zig_unreachable();
+}
+
+static IrInstruction *ir_resolve_result_runtime(IrAnalyze *ira, ResultLoc *result_loc, ZigType *elem_type) {
+ result_loc->implicit_elem_type = elem_type;
switch (result_loc->id) {
case ResultLocIdInvalid:
+ case ResultLocIdPeerParent:
zig_unreachable();
case ResultLocIdNone:
return nullptr;
@@ -14254,14 +14363,21 @@ static IrInstruction *ir_resolve_result_loc(IrAnalyze *ira, ResultLoc *result_lo
return alloca_src->base.child;
}
case ResultLocIdReturn: {
- //ResultLocReturn *result_loc_ret = reinterpret_cast(result_loc);
- // TODO implicit cast?
- return ir_build_return_ptr(ira, result_loc->source_instruction, elem_type);
+ ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false);
+ return ir_build_return_ptr(ira, result_loc->source_instruction, ptr_return_type);
}
+ case ResultLocIdPeer:
+ return nullptr;
}
zig_unreachable();
}
+static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, IrInstruction *value) {
+ IrInstruction *result_inst = ir_resolve_result_runtime(ira, result_loc, value->value.type);
+ result_loc->gen_instruction = value;
+ return result_inst;
+}
+
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
IrInstruction *async_allocator_inst)
@@ -14295,12 +14411,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
ZigType *promise_type = get_promise_type(ira->codegen, return_type);
ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
- IrInstruction *result_loc = ir_resolve_result_loc(ira, call_instruction->result_loc, async_return_type);
-
- IrInstruction *result = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
- casted_args, FnInlineAuto, true, async_allocator_inst, nullptr, result_loc);
- result->value.type = async_return_type;
- return result;
+ return ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
+ casted_args, FnInlineAuto, true, async_allocator_inst, nullptr, call_instruction->result_loc,
+ async_return_type);
}
static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
@@ -15053,12 +15166,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
}
assert(async_allocator_inst == nullptr);
- IrInstruction *result_loc = ir_resolve_result_loc(ira, call_instruction->result_loc,
- impl_fn_type_id->return_type);
IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
impl_fn, nullptr, impl_param_count, casted_args, fn_inline,
- call_instruction->is_async, nullptr, casted_new_stack, result_loc);
- new_call_instruction->value.type = impl_fn_type_id->return_type;
+ call_instruction->is_async, nullptr, casted_new_stack, call_instruction->result_loc,
+ impl_fn_type_id->return_type);
return ir_finish_anal(ira, new_call_instruction);
}
@@ -15152,10 +15263,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
return ira->codegen->invalid_instruction;
}
- IrInstruction *result_loc = ir_resolve_result_loc(ira, call_instruction->result_loc, return_type);
IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
- call_param_count, casted_args, fn_inline, false, nullptr, casted_new_stack, result_loc);
- new_call_instruction->value.type = return_type;
+ call_param_count, casted_args, fn_inline, false, nullptr, casted_new_stack,
+ call_instruction->result_loc, return_type);
return ir_finish_anal(ira, new_call_instruction);
}
@@ -23466,7 +23576,47 @@ static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, Ir
return ira->codegen->invalid_instruction;
}
-static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
+static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstructionEndExpr *instruction) {
+ IrInstruction *value = instruction->value->child;
+ if (type_is_invalid(value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ assert(instruction->lval == LValNone);
+
+ if (instruction->result_loc->id == ResultLocIdPeer) {
+ ResultLocPeer *result_peer = reinterpret_cast(instruction->result_loc);
+ ResultLocPeerParent *peer_parent = result_peer->parent;
+
+ if (peer_parent->resolved_type == nullptr && !ira->const_predecessor_bb) {
+ instruction->result_loc->implicit_elem_type = value->value.type;
+ instruction->result_loc->gen_instruction = value;
+ IrInstruction *suspended_inst = ira_suspend(ira, &instruction->base, result_peer->next_bb,
+ &result_peer->suspend_pos);
+ bool last_one = (result_peer == &peer_parent->peers[peer_parent->peer_count - 1]);
+ if (!last_one) {
+ return suspended_inst;
+ }
+ IrInstruction **instructions = allocate(peer_parent->peer_count);
+ for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
+ instructions[i] = peer_parent->peers[i].base.gen_instruction;
+ ira->resume_stack.append(peer_parent->peers[peer_parent->peer_count - i - 1].suspend_pos);
+ }
+ ZigType *expected_type = ir_result_loc_expected_type(ira, peer_parent->parent);
+ peer_parent->resolved_type = ir_resolve_peer_types(ira,
+ peer_parent->base.source_instruction->source_node, expected_type, instructions,
+ peer_parent->peer_count);
+ return ira_resume(ira);
+ }
+ }
+ IrInstruction *result_loc = ir_resolve_result(ira, instruction->result_loc, value);
+ if (result_loc != nullptr) {
+ ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
+ }
+
+ return ir_const_void(ira, &instruction->base);
+}
+
+static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdWidenOrShorten:
@@ -23769,17 +23919,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);
case IrInstructionIdAllocaSrc:
return nullptr;
+ case IrInstructionIdEndExpr:
+ return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);
}
zig_unreachable();
}
-static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);
- ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
- old_instruction->child = new_instruction;
- return new_instruction;
-}
-
// This function attempts to evaluate IR code while doing type checking and other analysis.
// It emits a new IrExecutable which is partially evaluated IR code.
ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
@@ -23825,8 +23970,11 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
continue;
}
- IrInstruction *new_instruction = ir_analyze_instruction(ira, old_instruction);
+ IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
if (new_instruction != nullptr) {
+ ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
+ old_instruction->child = new_instruction;
+
if (type_is_invalid(new_instruction->value.type) && ir_should_inline(new_exec, old_instruction->scope)) {
return ira->codegen->builtin_types.entry_invalid;
}
@@ -23907,6 +24055,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdResizeSlice:
case IrInstructionIdGlobalAsm:
case IrInstructionIdUndeclaredIdent:
+ case IrInstructionIdEndExpr:
return true;
case IrInstructionIdPhi:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 20581a65cf..8eb693671a 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -158,6 +158,16 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
zig_unreachable();
}
+static const char *ir_lval_str(LVal lval) {
+ switch (lval) {
+ case LValNone:
+ return "None";
+ case LValPtr:
+ return "Ptr";
+ }
+ zig_unreachable();
+}
+
static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id));
ir_print_other_instruction(irp, un_op_instruction->value);
@@ -219,6 +229,12 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
return;
case ResultLocIdVar:
return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
+ case ResultLocIdPeer:
+ fprintf(irp->f, "peer");
+ return;
+ case ResultLocIdPeerParent:
+ fprintf(irp->f, "peer_parent");
+ return;
}
zig_unreachable();
}
@@ -1128,6 +1144,14 @@ static void ir_print_alloca_gen(IrPrint *irp, IrInstructionAllocaGen *instructio
fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint);
}
+static void ir_print_end_expr(IrPrint *irp, IrInstructionEndExpr *instruction) {
+ fprintf(irp->f, "EndExpr(result=");
+ ir_print_result_loc(irp, instruction->result_loc);
+ fprintf(irp->f, ",value=");
+ ir_print_other_instruction(irp, instruction->value);
+ fprintf(irp->f, ",lval=%s)", ir_lval_str(instruction->lval));
+}
+
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
fprintf(irp->f, "inttoerr ");
ir_print_other_instruction(irp, instruction->target);
@@ -2014,6 +2038,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAllocaGen:
ir_print_alloca_gen(irp, (IrInstructionAllocaGen *)instruction);
break;
+ case IrInstructionIdEndExpr:
+ ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
--
cgit v1.2.3
From ccce3d852681bfe60bce92a6766b4f431dd73571 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 31 May 2019 01:36:57 -0400
Subject: no-copy semantics for function forwarding
```zig
fn foo() Foo {
return bar();
}
```
```llvm
define internal fastcc void @foo(%Foo* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
call fastcc void @bar(%Foo* sret %0), !dbg !52
ret void, !dbg !54
}
```
---
src/analyze.cpp | 2 +-
src/codegen.cpp | 8 ++++++--
src/ir.cpp | 11 +++++++++--
3 files changed, 16 insertions(+), 5 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/analyze.cpp b/src/analyze.cpp
index a62c24460e..24c81d2a3f 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -7278,6 +7278,6 @@ void src_assert(bool ok, AstNode *source_node) {
buf_ptr(source_node->owner->data.structure.root_struct->path),
(unsigned)source_node->line + 1, (unsigned)source_node->column + 1);
}
- const char *msg = "assertion failed";
+ const char *msg = "assertion failed. This is a bug in the Zig compiler.";
stage2_panic(msg, strlen(msg));
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index ccbf911686..d468b60183 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1995,7 +1995,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
if (!type_has_bits(instruction->value.type))
return nullptr;
if (!instruction->llvm_value) {
- assert(instruction->value.special != ConstValSpecialRuntime);
+ src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node);
assert(instruction->value.type);
render_const_val(g, &instruction->value, "");
// we might have to do some pointer casting here due to the way union
@@ -2388,7 +2388,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
assert(g->cur_ret_ptr);
- gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
+ if (return_instruction->value->value.special != ConstValSpecialRuntime) {
+ // if it's comptime we have to do this but if it's runtime trust that
+ // result location mechanism took care of it.
+ gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
+ }
LLVMBuildRetVoid(g->builder);
} else if (handle_is_ptr(return_type)) {
LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
diff --git a/src/ir.cpp b/src/ir.cpp
index f700404f29..3420a85fce 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1382,6 +1382,9 @@ static IrInstruction *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_in
FnInline fn_inline, bool is_async, IrInstruction *async_allocator, IrInstruction *new_stack,
ResultLoc *result_loc, ZigType *return_type)
{
+ // must be resolved before building the call instruction
+ IrInstruction *resolved_result_loc = ir_resolve_result(ira, result_loc, return_type, nullptr);
+
IrInstructionCallGen *call_instruction = ir_build_instruction(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
call_instruction->base.value.type = return_type;
@@ -1393,7 +1396,7 @@ static IrInstruction *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_in
call_instruction->is_async = is_async;
call_instruction->async_allocator = async_allocator;
call_instruction->new_stack = new_stack;
- call_instruction->result_loc = ir_resolve_result(ira, result_loc, return_type, nullptr);
+ call_instruction->result_loc = resolved_result_loc;
if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ira->new_irb.current_basic_block);
for (size_t i = 0; i < arg_count; i += 1)
@@ -14347,10 +14350,14 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_lo
}
// give nullptr for value to resolve it at runtime
-// returns a result location, or nullptr if the result location was already taken care of by this function
+// returns a result location, or nullptr if the result location was already taken care of
static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, ZigType *value_type,
IrInstruction *value)
{
+ if (result_loc->implicit_elem_type != nullptr) {
+ // already resolved
+ return nullptr;
+ }
result_loc->gen_instruction = value;
result_loc->implicit_elem_type = value_type;
switch (result_loc->id) {
--
cgit v1.2.3
From eb8a132d23c5c2a365eb3a8034a381cb74c3436c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 3 Jun 2019 17:46:58 -0400
Subject: var types, alignment, and comptime
---
BRANCH_TODO | 47 ++++++++++++++++++
src/all_types.hpp | 9 +++-
src/codegen.cpp | 1 +
src/ir.cpp | 145 +++++++++++++++++++++++++++---------------------------
src/ir_print.cpp | 23 ++++-----
5 files changed, 141 insertions(+), 84 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 85fc9d9e18..6509246908 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,6 +1,14 @@
Scratch pad for stuff to do before merging master
=================================================
+ * alignment of consts
+ * implicit casts
+ * for loops
+ * switch expression
+ * struct initializations
+ * function call parameters
+ * bitCast
+
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
migrate all the alloca_list to alloca_gen_list
@@ -22,3 +30,42 @@ inferred comptime
return ir_build_ref(irb, scope, value->source_node, value, false, false);
handle if with no else
+
+for loops:
+ IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
+
+ IrInstruction *elem_var_type;
+ if (node->data.for_expr.elem_is_ptr) {
+ elem_var_type = pointer_type;
+ } else {
+ elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
+ }
+ IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
+- do they need to have an implicit cast in there for the elem variable?
+static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
+ IrInstructionToPtrType *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->ptr = ptr;
+
+ ir_ref_instruction(ptr, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *value)
+{
+ IrInstructionPtrTypeChild *instruction = ir_build_instruction(
+ irb, scope, source_node);
+ instruction->value = value;
+
+ ir_ref_instruction(value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+coroutines
+ ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
+ IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
+- implicit cast for the var decl
+ IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
+ get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 79ad2f8958..c6346ca009 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2277,6 +2277,7 @@ enum IrInstructionId {
IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrType,
IrInstructionIdAlignCast,
+ IrInstructionIdImplicitCast,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
@@ -3581,7 +3582,13 @@ struct IrInstructionEndExpr {
IrInstruction *value;
ResultLoc *result_loc;
- LVal lval;
+};
+
+struct IrInstructionImplicitCast {
+ IrInstruction base;
+
+ IrInstruction *dest_type;
+ IrInstruction *target;
};
enum ResultLocId {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d468b60183..da4be1bf23 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5612,6 +5612,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdAllocaSrc:
case IrInstructionIdEndExpr:
case IrInstructionIdAllocaGen:
+ case IrInstructionIdImplicitCast:
zig_unreachable();
case IrInstructionIdDeclVarGen:
diff --git a/src/ir.cpp b/src/ir.cpp
index 3007edff84..35e71be1c2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -891,6 +891,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
return IrInstructionIdAlignCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *) {
+ return IrInstructionIdImplicitCast;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
return IrInstructionIdOpaqueType;
}
@@ -1574,17 +1578,15 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
}
static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *ptr)
+ ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)
{
IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction(irb, scope, source_node);
decl_var_instruction->base.value.special = ConstValSpecialStatic;
decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
decl_var_instruction->var = var;
- decl_var_instruction->var_type = var_type;
decl_var_instruction->align_value = align_value;
decl_var_instruction->ptr = ptr;
- if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
ir_ref_instruction(ptr, irb->current_basic_block);
@@ -1655,27 +1657,6 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
- IrInstructionToPtrType *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->ptr = ptr;
-
- ir_ref_instruction(ptr, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
-{
- IrInstructionPtrTypeChild *instruction = ir_build_instruction(
- irb, scope, source_node);
- instruction->value = value;
-
- ir_ref_instruction(value, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) {
IrInstructionSetCold *instruction = ir_build_instruction(irb, scope, source_node);
instruction->is_cold = is_cold;
@@ -2780,6 +2761,19 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *dest_type, IrInstruction *target)
+{
+ IrInstructionImplicitCast *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->target = target;
+
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionOpaqueType *instruction = ir_build_instruction(irb, scope, source_node);
@@ -3199,11 +3193,10 @@ static IrInstructionAllocaGen *ir_create_alloca_gen(IrAnalyze *ira, IrInstructio
}
static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value, LVal lval, ResultLoc *result_loc)
+ IrInstruction *value, ResultLoc *result_loc)
{
IrInstructionEndExpr *instruction = ir_build_instruction(irb, scope, source_node);
instruction->value = value;
- instruction->lval = lval;
instruction->result_loc = result_loc;
ir_ref_instruction(value, irb->current_basic_block);
@@ -5399,8 +5392,7 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
}
static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) {
- // TODO remove the lval parameter here
- ir_build_end_expr(irb, scope, inst->source_node, inst, LValNone, result_loc);
+ ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc);
return inst;
}
@@ -5607,9 +5599,12 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
return irb->codegen->invalid_instruction;
}
+ // Used for the type expr and the align expr
+ Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
+
IrInstruction *type_instruction;
if (variable_declaration->type != nullptr) {
- type_instruction = ir_gen_node(irb, variable_declaration->type, scope);
+ type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope);
if (type_instruction == irb->codegen->invalid_instruction)
return type_instruction;
} else {
@@ -5635,7 +5630,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
IrInstruction *align_value = nullptr;
if (variable_declaration->align_expr != nullptr) {
- align_value = ir_gen_node(irb, variable_declaration->align_expr, scope);
+ align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope);
if (align_value == irb->codegen->invalid_instruction)
return align_value;
}
@@ -5656,19 +5651,24 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
result_loc_var->base.id = ResultLocIdVar;
result_loc_var->base.source_instruction = alloca;
result_loc_var->var = var;
+ ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr;
// Temporarily set the name of the IrExecutable to the VariableDeclaration
// so that the struct or enum from the init expression inherits the name.
Buf *old_exec_name = irb->exec->name;
irb->exec->name = variable_declaration->symbol;
- IrInstruction *init_value = ir_gen_node_extra(irb, variable_declaration->expr, scope, LValNone,
- &result_loc_var->base);
+ IrInstruction *init_value = ir_gen_node_extra(irb, variable_declaration->expr, scope, LValNone, init_result_loc);
irb->exec->name = old_exec_name;
if (init_value == irb->codegen->invalid_instruction)
- return init_value;
+ return irb->codegen->invalid_instruction;
+
+ if (type_instruction != nullptr) {
+ IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value);
+ ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base);
+ }
- return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, alloca);
+ return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca);
}
static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -5725,7 +5725,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
err_val_ptr, false);
IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
- ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
+ ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_value);
}
ZigList incoming_values = {0};
@@ -5767,7 +5767,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
true, false, false, is_comptime);
Scope *err_scope = err_var->child_scope;
IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
- ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
+ ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_var_value);
IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
if (else_result == irb->codegen->invalid_instruction)
@@ -5811,7 +5811,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
- ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
+ ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_value);
ZigList incoming_values = {0};
ZigList incoming_blocks = {0};
@@ -5953,14 +5953,6 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
if (array_val_ptr == irb->codegen->invalid_instruction)
return array_val_ptr;
- IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
- IrInstruction *elem_var_type;
- if (node->data.for_expr.elem_is_ptr) {
- elem_var_type = pointer_type;
- } else {
- elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
- }
-
IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
@@ -5970,7 +5962,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
Scope *child_scope = elem_var->child_scope;
IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
- ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
+ ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, nullptr, undefined_value);
IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
AstNode *index_var_source_node;
@@ -5985,10 +5977,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
}
child_scope = index_var->child_scope;
- IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
- ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
+ ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, nullptr, zero);
IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
@@ -6380,7 +6371,6 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
Scope *var_scope;
if (var_symbol) {
- IrInstruction *var_type = nullptr;
bool is_shadowable = false;
bool is_const = true;
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
@@ -6388,7 +6378,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_value);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
@@ -6455,7 +6445,6 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
Scope *var_scope;
if (var_symbol) {
- IrInstruction *var_type = nullptr;
bool is_shadowable = false;
IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val);
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
@@ -6463,7 +6452,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_value);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
@@ -6481,14 +6470,13 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
if (else_node) {
Scope *err_var_scope;
if (err_symbol) {
- IrInstruction *var_type = nullptr;
bool is_shadowable = false;
bool is_const = true;
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
err_symbol, is_const, is_const, is_shadowable, is_comptime);
IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_value);
err_var_scope = var->child_scope;
} else {
err_var_scope = subexpr_scope;
@@ -6551,8 +6539,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node,
target_value_ptr);
}
- IrInstruction *var_type = nullptr; // infer the type
- ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, scope, var_symbol_node, var, nullptr, var_value);
} else {
child_scope = scope;
}
@@ -7018,7 +7005,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
is_const, is_const, is_shadowable, is_comptime);
err_scope = var->child_scope;
IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
- ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
+ ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_val);
} else {
err_scope = parent_scope;
}
@@ -7509,7 +7496,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
- ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
+ ir_build_var_decl_src(irb, scope, node, result_var, nullptr, undefined_value);
IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
@@ -7940,17 +7927,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
- ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
- IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
// TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
- ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
+ ir_build_var_decl_src(irb, coro_scope, node, promise_var, nullptr, undef);
coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
- IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
- get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
- ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
+ ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, nullptr, null_value);
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
@@ -7960,11 +7943,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
- ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
+ ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, coro_size);
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
ImplicitAllocatorIdArg);
irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
- ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
+ ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, implicit_allocator_ptr);
Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name);
IrInstruction *realloc_fn = ir_build_load_ptr(irb, coro_scope, node, realloc_fn_ptr);
@@ -14375,20 +14358,24 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, Z
case ResultLocIdNone:
return nullptr;
case ResultLocIdVar: {
- // TODO implicit cast?
ResultLocVar *result_loc_var = reinterpret_cast(result_loc);
assert(result_loc->source_instruction->id == IrInstructionIdAllocaSrc);
IrInstructionAllocaSrc *alloca_src =
reinterpret_cast(result_loc->source_instruction);
if (alloca_src->base.child == nullptr) {
- uint32_t align = 0; // TODO
- bool force_comptime = false; // TODO
bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime &&
result_loc_var->var->gen_is_const;
IrInstruction *alloca_gen;
if (is_comptime) {
alloca_gen = ir_get_ref(ira, result_loc->source_instruction, value, true, false);
} else {
+ uint32_t align = 0;
+ if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
+ return ira->codegen->invalid_instruction;
+ }
+ bool force_comptime;
+ if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime))
+ return ira->codegen->invalid_instruction;
alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align,
alloca_src->name_hint, force_comptime);
}
@@ -14409,6 +14396,19 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, Z
zig_unreachable();
}
+static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *target = instruction->target->child;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_implicit_cast(ira, target, dest_type);
+}
+
+
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
IrInstruction *async_allocator_inst)
@@ -23612,8 +23612,6 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
- assert(instruction->lval == LValNone);
-
if (instruction->result_loc->id == ResultLocIdPeer) {
ResultLocPeer *result_peer = reinterpret_cast(instruction->result_loc);
ResultLocPeerParent *peer_parent = result_peer->parent;
@@ -23640,7 +23638,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
}
}
IrInstruction *result_loc = ir_resolve_result(ira, instruction->result_loc, value->value.type, value);
- if (result_loc != nullptr) {
+ if (result_loc != nullptr && !type_is_invalid(result_loc->value.type)) {
ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
}
@@ -23874,6 +23872,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_ptr_type(ira, (IrInstructionPtrType *)instruction);
case IrInstructionIdAlignCast:
return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
+ case IrInstructionIdImplicitCast:
+ return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
case IrInstructionIdOpaqueType:
return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
case IrInstructionIdSetAlignStack:
@@ -24165,6 +24165,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTypeInfo:
case IrInstructionIdTypeId:
case IrInstructionIdAlignCast:
+ case IrInstructionIdImplicitCast:
case IrInstructionIdOpaqueType:
case IrInstructionIdArgType:
case IrInstructionIdTagType:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 8eb693671a..fca5f2edc2 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -158,16 +158,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
zig_unreachable();
}
-static const char *ir_lval_str(LVal lval) {
- switch (lval) {
- case LValNone:
- return "None";
- case LValPtr:
- return "Ptr";
- }
- zig_unreachable();
-}
-
static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id));
ir_print_other_instruction(irp, un_op_instruction->value);
@@ -1149,7 +1139,7 @@ static void ir_print_end_expr(IrPrint *irp, IrInstructionEndExpr *instruction) {
ir_print_result_loc(irp, instruction->result_loc);
fprintf(irp->f, ",value=");
ir_print_other_instruction(irp, instruction->value);
- fprintf(irp->f, ",lval=%s)", ir_lval_str(instruction->lval));
+ fprintf(irp->f, ")");
}
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
@@ -1274,6 +1264,14 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio
fprintf(irp->f, ")");
}
+static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) {
+ fprintf(irp->f, "@implicitCast(");
+ ir_print_other_instruction(irp, instruction->dest_type);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
fprintf(irp->f, "@OpaqueType()");
}
@@ -1912,6 +1910,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAlignCast:
ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);
break;
+ case IrInstructionIdImplicitCast:
+ ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction);
+ break;
case IrInstructionIdOpaqueType:
ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
break;
--
cgit v1.2.3
From b6108eed522b7a0122d305dc1a74de8f12f20d5b Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 3 Jun 2019 19:11:41 -0400
Subject: fix alignment of consts
---
BRANCH_TODO | 1 -
src/all_types.hpp | 1 +
src/codegen.cpp | 3 ++-
src/ir.cpp | 21 ++++++++++++---------
4 files changed, 15 insertions(+), 11 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 6509246908..e809e2b4d8 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,7 +1,6 @@
Scratch pad for stuff to do before merging master
=================================================
- * alignment of consts
* implicit casts
* for loops
* switch expression
diff --git a/src/all_types.hpp b/src/all_types.hpp
index c6346ca009..0df5384c7a 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -292,6 +292,7 @@ struct RuntimeHintSlice {
struct ConstGlobalRefs {
LLVMValueRef llvm_value;
LLVMValueRef llvm_global;
+ uint32_t align;
};
struct ConstExprValue {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index da4be1bf23..b03068eb7d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -6599,7 +6599,8 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
LLVMSetLinkage(global_value, LLVMInternalLinkage);
LLVMSetGlobalConstant(global_value, true);
LLVMSetUnnamedAddr(global_value, true);
- LLVMSetAlignment(global_value, get_abi_alignment(g, const_val->type));
+ LLVMSetAlignment(global_value, (const_val->global_refs->align == 0) ?
+ get_abi_alignment(g, const_val->type) : const_val->global_refs->align);
const_val->global_refs->llvm_global = global_value;
}
diff --git a/src/ir.cpp b/src/ir.cpp
index 35e71be1c2..f8e77cdd72 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -14363,19 +14363,22 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, Z
IrInstructionAllocaSrc *alloca_src =
reinterpret_cast(result_loc->source_instruction);
if (alloca_src->base.child == nullptr) {
- bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime &&
- result_loc_var->var->gen_is_const;
+ bool force_comptime;
+ if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime))
+ return ira->codegen->invalid_instruction;
+ bool is_comptime = force_comptime || (value != nullptr &&
+ value->value.special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const);
+ uint32_t align = 0;
+ if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
+ return ira->codegen->invalid_instruction;
+ }
IrInstruction *alloca_gen;
if (is_comptime) {
+ if (align > value->value.global_refs->align) {
+ value->value.global_refs->align = align;
+ }
alloca_gen = ir_get_ref(ira, result_loc->source_instruction, value, true, false);
} else {
- uint32_t align = 0;
- if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
- return ira->codegen->invalid_instruction;
- }
- bool force_comptime;
- if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime))
- return ira->codegen->invalid_instruction;
alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align,
alloca_src->name_hint, force_comptime);
}
--
cgit v1.2.3
From d4054e35fe3a6ba4b4f0d1a0da0e0149f21b49a4 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 3 Jun 2019 20:56:22 -0400
Subject: while loops
Note that neither the payload capture variable nor the error capture
variable require a stack allocation.
```zig
export fn entry() void {
var c: anyerror!i32 = 1234;
while (c) |hi| {} else |e| {}
}
```
```llvm
define void @entry() #2 !dbg !39 {
Entry:
%c = alloca { i16, i32 }, align 4
%0 = bitcast { i16, i32 }* %c to i8*, !dbg !52
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 bitcast ({ i16, i32 }* @0 to i8*), i64 8, i1 false), !dbg !52
call void @llvm.dbg.declare(metadata { i16, i32 }* %c, metadata !43, metadata !DIExpression()), !dbg !52
br label %WhileCond, !dbg !53
WhileCond: ; preds = %WhileBody, %Entry
%1 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %c, i32 0, i32 0, !dbg !54
%2 = load i16, i16* %1, align 2, !dbg !54
%3 = icmp ne i16 %2, 0, !dbg !54
br i1 %3, label %WhileElse, label %WhileBody, !dbg !54
WhileBody: ; preds = %WhileCond
%4 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %c, i32 0, i32 1, !dbg !53
call void @llvm.dbg.declare(metadata i32* %4, metadata !50, metadata !DIExpression()), !dbg !53
br label %WhileCond, !dbg !53
WhileElse: ; preds = %WhileCond
%5 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %c, i32 0, i32 0, !dbg !55
call void @llvm.dbg.declare(metadata i16* %5, metadata !51, metadata !DIExpression()), !dbg !55
ret void, !dbg !56
}
```
---
BRANCH_TODO | 43 ++--------------------
src/all_types.hpp | 3 +-
src/codegen.cpp | 14 ++++----
src/ir.cpp | 106 ++++++++++++++++++++++++++++++++++++++----------------
src/ir_print.cpp | 2 +-
5 files changed, 86 insertions(+), 82 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index e809e2b4d8..c85a7aea81 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,7 +1,8 @@
Scratch pad for stuff to do before merging master
=================================================
- * implicit casts
+migrate ir_build_var_decl_src to use ir_build_alloca_src and explicitly initialize
+
* for loops
* switch expression
* struct initializations
@@ -12,8 +13,6 @@ look at all the ir_gen_node ir_gen_node_extra calls and make sure result locatio
migrate all the alloca_list to alloca_gen_list
-migrate ir_build_var_decl_src to use ir_build_alloca_src and explicitly initialize
-
inferred comptime
@@ -30,41 +29,3 @@ inferred comptime
handle if with no else
-for loops:
- IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
-
- IrInstruction *elem_var_type;
- if (node->data.for_expr.elem_is_ptr) {
- elem_var_type = pointer_type;
- } else {
- elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
- }
- IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
-- do they need to have an implicit cast in there for the elem variable?
-static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
- IrInstructionToPtrType *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->ptr = ptr;
-
- ir_ref_instruction(ptr, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
-{
- IrInstructionPtrTypeChild *instruction = ir_build_instruction(
- irb, scope, source_node);
- instruction->value = value;
-
- ir_ref_instruction(value, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-coroutines
- ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
- IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
-- implicit cast for the var decl
- IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
- get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 0df5384c7a..8726c562d9 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3087,10 +3087,11 @@ struct IrInstructionTestErr {
IrInstruction *value;
};
+// Takes an error union pointer, returns a pointer to the error code.
struct IrInstructionUnwrapErrCode {
IrInstruction base;
- IrInstruction *err_union;
+ IrInstruction *err_union_ptr;
};
struct IrInstructionUnwrapErrPayload {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index b03068eb7d..84d5777530 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4878,18 +4878,16 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
IrInstructionUnwrapErrCode *instruction)
{
- ZigType *ptr_type = instruction->err_union->value.type;
+ ZigType *ptr_type = instruction->err_union_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *err_union_type = ptr_type->data.pointer.child_type;
ZigType *payload_type = err_union_type->data.error_union.payload_type;
- LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
- LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
-
- if (type_has_bits(payload_type)) {
- LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
- return gen_load_untyped(g, err_val_ptr, 0, false, "");
+ LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr);
+ if (!type_has_bits(payload_type)) {
+ return err_union_ptr;
} else {
- return err_union_handle;
+ LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
+ return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
}
}
diff --git a/src/ir.cpp b/src/ir.cpp
index f8e77cdd72..1afa435d19 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1657,6 +1657,27 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
+static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
+ IrInstructionToPtrType *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->ptr = ptr;
+
+ ir_ref_instruction(ptr, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *value)
+{
+ IrInstructionPtrTypeChild *instruction = ir_build_instruction(
+ irb, scope, source_node);
+ instruction->value = value;
+
+ ir_ref_instruction(value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) {
IrInstructionSetCold *instruction = ir_build_instruction(irb, scope, source_node);
instruction->is_cold = is_cold;
@@ -2371,12 +2392,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
}
static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *err_union)
+ IrInstruction *err_union_ptr)
{
IrInstructionUnwrapErrCode *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->err_union = err_union;
+ instruction->err_union_ptr = err_union_ptr;
- ir_ref_instruction(err_union, irb->current_basic_block);
+ ir_ref_instruction(err_union_ptr, irb->current_basic_block);
return &instruction->base;
}
@@ -3505,7 +3526,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_set_cursor_at_end_and_append_block(irb, return_block);
if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
- IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
+ IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
+ IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
if (irb->codegen->have_err_ret_tracing && !should_inline) {
ir_build_save_err_ret_addr(irb, scope, node);
}
@@ -5721,11 +5743,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, body_block);
if (var_symbol) {
- IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
+ IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
err_val_ptr, false);
- IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
- var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
- ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_value);
+ IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
+ ir_build_ref(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
+ ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);
}
ZigList incoming_values = {0};
@@ -5766,8 +5788,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol,
true, false, false, is_comptime);
Scope *err_scope = err_var->child_scope;
- IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
- ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_var_value);
+ IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
+ ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);
IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
if (else_result == irb->codegen->invalid_instruction)
@@ -5808,10 +5830,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
}
ir_set_cursor_at_end_and_append_block(irb, body_block);
- IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
- IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
- var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
- ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_value);
+ IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
+ IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
+ ir_build_ref(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
+ ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);
ZigList incoming_values = {0};
ZigList incoming_blocks = {0};
@@ -5953,6 +5975,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
if (array_val_ptr == irb->codegen->invalid_instruction)
return array_val_ptr;
+ IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
+
+ IrInstruction *elem_var_type;
+ if (node->data.for_expr.elem_is_ptr) {
+ elem_var_type = pointer_type;
+ } else {
+ elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
+ }
+
IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
@@ -5961,8 +5992,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
Scope *child_scope = elem_var->child_scope;
- IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
- ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, nullptr, undefined_value);
+ IrInstruction *undef = ir_build_const_undefined(irb, parent_scope, elem_node);
+ IrInstruction *undef_elem_var_type = ir_build_implicit_cast(irb, parent_scope, elem_node, elem_var_type, undef);
+ ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, nullptr, undef_elem_var_type);
IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
AstNode *index_var_source_node;
@@ -6475,8 +6507,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
err_symbol, is_const, is_const, is_shadowable, is_comptime);
- IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_value);
+ IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, err_ptr);
err_var_scope = var->child_scope;
} else {
err_var_scope = subexpr_scope;
@@ -7004,8 +7036,8 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
ZigVar *var = ir_create_var(irb, node, parent_scope, var_name,
is_const, is_const, is_shadowable, is_comptime);
err_scope = var->child_scope;
- IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
- ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_val);
+ IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
+ ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_ptr);
} else {
err_scope = parent_scope;
}
@@ -7482,7 +7514,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise);
IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);
- IrInstruction *undefined_value = ir_build_const_undefined(irb, scope, node);
+ IrInstruction *undef = ir_build_const_undefined(irb, scope, node);
IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111
@@ -7496,7 +7528,8 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
- ir_build_var_decl_src(irb, scope, node, result_var, nullptr, undefined_value);
+ IrInstruction *undef_promise_result = ir_build_implicit_cast(irb, scope, node, promise_result_type, undef);
+ ir_build_var_decl_src(irb, scope, node, result_var, nullptr, undef_promise_result);
IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
@@ -7928,12 +7961,18 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
// TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
- ir_build_var_decl_src(irb, coro_scope, node, promise_var, nullptr, undef);
+ ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
+ IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
+ IrInstruction *undef_coro_frame = ir_build_implicit_cast(irb, coro_scope, node, coro_frame_type_value, undef);
+ ir_build_var_decl_src(irb, coro_scope, node, promise_var, nullptr, undef_coro_frame);
coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
- ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, nullptr, null_value);
+ IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
+ get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
+ IrInstruction *null_await_handle = ir_build_implicit_cast(irb, coro_scope, node, await_handle_type_val, null_value);
+ ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, nullptr, null_await_handle);
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
@@ -13872,7 +13911,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
return ira->codegen->invalid_instruction;
}
- assert(var_ptr->value.type->id == ZigTypeIdPointer);
+ // The ir_build_var_decl_src call is supposed to pass a pointer to the allocation, not an initialization value.
+ ir_assert(var_ptr->value.type->id == ZigTypeIdPointer, &decl_var_instruction->base);
ZigType *result_type = var_ptr->value.type->data.pointer.child_type;
if (type_is_invalid(result_type)) {
@@ -21526,13 +21566,14 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
}
static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
- IrInstruction *base_ptr = instruction->err_union->child;
+ IrInstruction *base_ptr = instruction->err_union_ptr->child;
if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
ZigType *ptr_type = base_ptr->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
assert(ptr_type->id == ZigTypeIdPointer);
+ bool is_ptr_const = ptr_type->data.pointer.is_const;
ZigType *type_entry = ptr_type->data.pointer.child_type;
if (type_is_invalid(type_entry))
@@ -21554,19 +21595,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI
return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
- assert(err);
+ assert(err != nullptr);
- IrInstruction *result = ir_const(ira, &instruction->base,
+ IrInstruction *err_set_val = ir_const(ira, &instruction->base,
type_entry->data.error_union.err_set_type);
- result->value.data.x_err_set = err;
- return result;
+ err_set_val->value.data.x_err_set = err;
+ err_set_val->value.parent.id = ConstParentIdErrUnionCode;
+ err_set_val->value.parent.data.p_err_union_code.err_union_val = err_union_val;
+
+ return ir_get_ref(ira, &instruction->base, err_set_val, is_ptr_const, false);
}
}
}
IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
instruction->base.scope, instruction->base.source_node, base_ptr);
- result->value.type = type_entry->data.error_union.err_set_type;
+ result->value.type = get_pointer_to_type(ira->codegen, type_entry->data.error_union.err_set_type, is_ptr_const);
return result;
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index fca5f2edc2..7906d57be0 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -957,7 +957,7 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
fprintf(irp->f, "UnwrapErrorCode(");
- ir_print_other_instruction(irp, instruction->err_union);
+ ir_print_other_instruction(irp, instruction->err_union_ptr);
fprintf(irp->f, ")");
}
--
cgit v1.2.3
From 143d6ada8f93872b94a8f20927e11cae243028d9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 3 Jun 2019 21:40:56 -0400
Subject: no-copy semantics for for loops
Note that only the index variable requires a stack allocation, and the
memcpy for the element is gone.
```zig
export fn entry() void {
var buf: [10]i32 = undefined;
for (buf) |x| {}
}
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%buf = alloca [10 x i32], align 4
%i = alloca i64, align 8
%0 = bitcast [10 x i32]* %buf to i8*, !dbg !47
call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 -86, i64 40, i1 false), !dbg !47
call void @llvm.dbg.declare(metadata [10 x i32]* %buf, metadata !39, metadata !DIExpression()), !dbg !47
store i64 0, i64* %i, align 8, !dbg !48
call void @llvm.dbg.declare(metadata i64* %i, metadata !45, metadata !DIExpression()), !dbg !48
br label %ForCond, !dbg !48
ForCond: ; preds = %ForBody, %Entry
%1 = load i64, i64* %i, align 8, !dbg !48
%2 = icmp ult i64 %1, 10, !dbg !48
br i1 %2, label %ForBody, label %ForEnd, !dbg !48
ForBody: ; preds = %ForCond
%3 = getelementptr inbounds [10 x i32], [10 x i32]* %buf, i64 0, i64 %1, !dbg !48
call void @llvm.dbg.declare(metadata i32* %3, metadata !46, metadata !DIExpression()), !dbg !49
%4 = add nuw i64 %1, 1, !dbg !48
store i64 %4, i64* %i, align 8, !dbg !48
br label %ForCond, !dbg !48
ForEnd: ; preds = %ForCond
ret void, !dbg !50
}
```
---
BRANCH_TODO | 1 -
src/all_types.hpp | 14 ----
src/codegen.cpp | 2 -
src/ir.cpp | 187 +++++++++++++-----------------------------------------
src/ir_print.cpp | 18 ------
5 files changed, 44 insertions(+), 178 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index c85a7aea81..70fad23791 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -3,7 +3,6 @@ Scratch pad for stuff to do before merging master
migrate ir_build_var_decl_src to use ir_build_alloca_src and explicitly initialize
- * for loops
* switch expression
* struct initializations
* function call parameters
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 8726c562d9..6f504efd9c 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2191,8 +2191,6 @@ enum IrInstructionId {
IrInstructionIdUnionInit,
IrInstructionIdUnreachable,
IrInstructionIdTypeOf,
- IrInstructionIdToPtrType,
- IrInstructionIdPtrTypeChild,
IrInstructionIdSetCold,
IrInstructionIdSetRuntimeSafety,
IrInstructionIdSetFloatMode,
@@ -2679,18 +2677,6 @@ struct IrInstructionTypeOf {
IrInstruction *value;
};
-struct IrInstructionToPtrType {
- IrInstruction base;
-
- IrInstruction *ptr;
-};
-
-struct IrInstructionPtrTypeChild {
- IrInstruction base;
-
- IrInstruction *value;
-};
-
struct IrInstructionSetCold {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 84d5777530..eecc2239db 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5539,8 +5539,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdInvalid:
case IrInstructionIdConst:
case IrInstructionIdTypeOf:
- case IrInstructionIdToPtrType:
- case IrInstructionIdPtrTypeChild:
case IrInstructionIdFieldPtr:
case IrInstructionIdSetCold:
case IrInstructionIdSetRuntimeSafety:
diff --git a/src/ir.cpp b/src/ir.cpp
index 1afa435d19..3b0ed7a17d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -523,14 +523,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) {
return IrInstructionIdTypeOf;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionToPtrType *) {
- return IrInstructionIdToPtrType;
-}
-
-static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) {
- return IrInstructionIdPtrTypeChild;
-}
-
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetCold *) {
return IrInstructionIdSetCold;
}
@@ -1657,27 +1649,6 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
- IrInstructionToPtrType *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->ptr = ptr;
-
- ir_ref_instruction(ptr, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
-{
- IrInstructionPtrTypeChild *instruction = ir_build_instruction(
- irb, scope, source_node);
- instruction->value = value;
-
- ir_ref_instruction(value, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) {
IrInstructionSetCold *instruction = ir_build_instruction(irb, scope, source_node);
instruction->is_cold = is_cold;
@@ -5611,6 +5582,14 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
}
}
+static ResultLocVar *create_var_result_loc(IrInstruction *alloca, ZigVar *var) {
+ ResultLocVar *result_loc_var = allocate(1);
+ result_loc_var->base.id = ResultLocIdVar;
+ result_loc_var->base.source_instruction = alloca;
+ result_loc_var->var = var;
+ return result_loc_var;
+}
+
static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeVariableDeclaration);
@@ -5669,10 +5648,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
buf_ptr(variable_declaration->symbol), is_comptime);
// Create a result location for the initialization expression.
- ResultLocVar *result_loc_var = allocate(1);
- result_loc_var->base.id = ResultLocIdVar;
- result_loc_var->base.source_instruction = alloca;
- result_loc_var->var = var;
+ ResultLocVar *result_loc_var = create_var_result_loc(alloca, var);
ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr;
// Temporarily set the name of the IrExecutable to the VariableDeclaration
@@ -5975,73 +5951,62 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
if (array_val_ptr == irb->codegen->invalid_instruction)
return array_val_ptr;
- IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
-
- IrInstruction *elem_var_type;
- if (node->data.for_expr.elem_is_ptr) {
- elem_var_type = pointer_type;
- } else {
- elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
- }
-
IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
- // TODO make it an error to write to element variable or i variable.
- Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
- ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
- Scope *child_scope = elem_var->child_scope;
-
- IrInstruction *undef = ir_build_const_undefined(irb, parent_scope, elem_node);
- IrInstruction *undef_elem_var_type = ir_build_implicit_cast(irb, parent_scope, elem_node, elem_var_type, undef);
- ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, nullptr, undef_elem_var_type);
- IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
-
AstNode *index_var_source_node;
ZigVar *index_var;
+ const char *index_var_name;
if (index_node) {
index_var_source_node = index_node;
- Buf *index_var_name = index_node->data.symbol_expr.symbol;
- index_var = ir_create_var(irb, index_node, child_scope, index_var_name, true, false, false, is_comptime);
+ Buf *index_var_name_buf = index_node->data.symbol_expr.symbol;
+ index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime);
+ index_var_name = buf_ptr(index_var_name_buf);
} else {
index_var_source_node = node;
- index_var = ir_create_var(irb, node, child_scope, nullptr, true, false, true, is_comptime);
+ index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime);
+ index_var_name = "i";
}
- child_scope = index_var->child_scope;
+ parent_scope = index_var->parent_scope;
- IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
- IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
- ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, nullptr, zero);
- IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
+ IrInstruction *index_alloca = ir_build_alloca_src(irb, parent_scope, node, nullptr, index_var_name, is_comptime);
+ ResultLocVar *var_result_loc = create_var_result_loc(index_alloca, index_var);
+ IrInstruction *zero = ir_build_const_usize(irb, parent_scope, node, 0);
+ ir_build_end_expr(irb, parent_scope, node, zero, &var_result_loc->base);
+ ir_build_var_decl_src(irb, parent_scope, index_var_source_node, index_var, nullptr, index_alloca);
+ IrInstruction *one = ir_build_const_usize(irb, parent_scope, node, 1);
+ IrInstruction *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var);
- IrBasicBlock *cond_block = ir_create_basic_block(irb, child_scope, "ForCond");
- IrBasicBlock *body_block = ir_create_basic_block(irb, child_scope, "ForBody");
- IrBasicBlock *end_block = ir_create_basic_block(irb, child_scope, "ForEnd");
- IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, child_scope, "ForElse") : end_block;
- IrBasicBlock *continue_block = ir_create_basic_block(irb, child_scope, "ForContinue");
+
+ IrBasicBlock *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond");
+ IrBasicBlock *body_block = ir_create_basic_block(irb, parent_scope, "ForBody");
+ IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd");
+ IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block;
+ IrBasicBlock *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue");
Buf *len_field_name = buf_create_from_str("len");
- IrInstruction *len_ref = ir_build_field_ptr(irb, child_scope, node, array_val_ptr, len_field_name);
- IrInstruction *len_val = ir_build_load_ptr(irb, child_scope, node, len_ref);
- ir_build_br(irb, child_scope, node, cond_block, is_comptime);
+ IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name);
+ IrInstruction *len_val = ir_build_load_ptr(irb, parent_scope, node, len_ref);
+ ir_build_br(irb, parent_scope, node, cond_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, cond_block);
- IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
- IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
+ IrInstruction *index_val = ir_build_load_ptr(irb, parent_scope, node, index_ptr);
+ IrInstruction *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));
- ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));
+ ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, body_block, else_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, body_block);
- IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false, PtrLenSingle);
- IrInstruction *elem_val;
- if (node->data.for_expr.elem_is_ptr) {
- elem_val = elem_ptr;
- } else {
- elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr);
- }
- ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val));
+ IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false, PtrLenSingle);
+ // TODO make it an error to write to element variable or i variable.
+ Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
+ ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
+ Scope *child_scope = elem_var->child_scope;
+
+ IrInstruction *var_ptr = node->data.for_expr.elem_is_ptr ?
+ ir_build_ref(irb, parent_scope, elem_node, elem_ptr, true, false) : elem_ptr;
+ ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr);
ZigList incoming_values = {0};
ZigList incoming_blocks = {0};
@@ -16901,64 +16866,6 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
return ir_const_type(ira, &typeof_instruction->base, type_entry);
}
-static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
- IrInstructionToPtrType *to_ptr_type_instruction)
-{
- Error err;
- IrInstruction *ptr_ptr = to_ptr_type_instruction->ptr->child;
- if (type_is_invalid(ptr_ptr->value.type))
- return ira->codegen->invalid_instruction;
-
- ZigType *ptr_ptr_type = ptr_ptr->value.type;
- assert(ptr_ptr_type->id == ZigTypeIdPointer);
- ZigType *type_entry = ptr_ptr_type->data.pointer.child_type;
-
- ZigType *ptr_type;
- if (type_entry->id == ZigTypeIdArray) {
- ptr_type = get_pointer_to_type(ira->codegen, type_entry->data.array.child_type, ptr_ptr_type->data.pointer.is_const);
- } else if (is_array_ref(type_entry)) {
- ptr_type = get_pointer_to_type(ira->codegen,
- type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
- } else if (is_slice(type_entry)) {
- ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry;
- ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle);
- // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type.
- if (slice_ptr_type->data.pointer.explicit_alignment != 0) {
- ZigType *elem_type = slice_ptr_type->data.pointer.child_type;
- if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
- return ira->codegen->invalid_instruction;
- uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type);
- uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment);
- ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align);
- }
- } else if (type_entry->id == ZigTypeIdArgTuple) {
- zig_panic("TODO for loop on var args");
- } else {
- ir_add_error_node(ira, to_ptr_type_instruction->base.source_node,
- buf_sprintf("expected array type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->invalid_instruction;
- }
-
- return ir_const_type(ira, &to_ptr_type_instruction->base, ptr_type);
-}
-
-static IrInstruction *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
- IrInstructionPtrTypeChild *ptr_type_child_instruction)
-{
- IrInstruction *type_value = ptr_type_child_instruction->value->child;
- ZigType *type_entry = ir_resolve_type(ira, type_value);
- if (type_is_invalid(type_entry))
- return ira->codegen->invalid_instruction;
-
- if (type_entry->id != ZigTypeIdPointer) {
- ir_add_error_node(ira, ptr_type_child_instruction->base.source_node,
- buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->invalid_instruction;
- }
-
- return ir_const_type(ira, &ptr_type_child_instruction->base, type_entry->data.pointer.child_type);
-}
-
static IrInstruction *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) {
if (ira->new_irb.exec->is_inline) {
// ignore setCold when running functions at compile time
@@ -23751,10 +23658,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
case IrInstructionIdTypeOf:
return ir_analyze_instruction_typeof(ira, (IrInstructionTypeOf *)instruction);
- case IrInstructionIdToPtrType:
- return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
- case IrInstructionIdPtrTypeChild:
- return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
case IrInstructionIdSetCold:
return ir_analyze_instruction_set_cold(ira, (IrInstructionSetCold *)instruction);
case IrInstructionIdSetRuntimeSafety:
@@ -24152,8 +24055,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdVarPtr:
case IrInstructionIdReturnPtr:
case IrInstructionIdTypeOf:
- case IrInstructionIdToPtrType:
- case IrInstructionIdPtrTypeChild:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdUnionFieldPtr:
case IrInstructionIdArrayType:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 7906d57be0..dbc5ea364c 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -414,18 +414,6 @@ static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
fprintf(irp->f, ")");
}
-static void ir_print_to_ptr_type(IrPrint *irp, IrInstructionToPtrType *instruction) {
- fprintf(irp->f, "@toPtrType(");
- ir_print_other_instruction(irp, instruction->ptr);
- fprintf(irp->f, ")");
-}
-
-static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *instruction) {
- fprintf(irp->f, "@ptrTypeChild(");
- ir_print_other_instruction(irp, instruction->value);
- fprintf(irp->f, ")");
-}
-
static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) {
if (instruction->field_name_buffer) {
fprintf(irp->f, "fieldptr ");
@@ -1625,12 +1613,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTypeOf:
ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
break;
- case IrInstructionIdToPtrType:
- ir_print_to_ptr_type(irp, (IrInstructionToPtrType *)instruction);
- break;
- case IrInstructionIdPtrTypeChild:
- ir_print_ptr_type_child(irp, (IrInstructionPtrTypeChild *)instruction);
- break;
case IrInstructionIdFieldPtr:
ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
break;
--
cgit v1.2.3
From 771e88951a9af48335abe14e4c44b5c4f5b252de Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 8 Jun 2019 18:51:31 -0400
Subject: result location mechanism for struct initialization
```zig
export fn entry() void {
const static = Foo{
.x = 9,
.bar = Bar{ .y = 10 },
};
const runtime = foo(true);
}
fn foo(c: bool) Foo {
return Foo{
.x = 12,
.bar = if (c) bar1() else bar2(),
};
}
fn bar1() Bar {
return Bar{ .y = 34 };
}
fn bar2() Bar {
return Bar{ .y = 56 };
}
```
```llvm
@0 = internal unnamed_addr constant %Foo { i32 9, %Bar { i32 10 } }, align 4
@1 = internal unnamed_addr constant %Bar { i32 34 }, align 4
@2 = internal unnamed_addr constant %Bar { i32 56 }, align 4
define void @entry() #2 !dbg !35 {
Entry:
%runtime = alloca %Foo, align 4
call void @llvm.dbg.declare(metadata %Foo* @0, metadata !39, metadata !DIExpression()), !dbg !50
call fastcc void @foo(%Foo* sret %runtime, i1 true), !dbg !51
call void @llvm.dbg.declare(metadata %Foo* %runtime, metadata !49, metadata !DIExpression()), !dbg !52
ret void, !dbg !53
}
define internal fastcc void @foo(%Foo* nonnull sret, i1) unnamed_addr #2 !dbg !54 {
Entry:
%c = alloca i1, align 1
store i1 %1, i1* %c, align 1
call void @llvm.dbg.declare(metadata i1* %c, metadata !60, metadata !DIExpression()), !dbg !61
%2 = getelementptr inbounds %Foo, %Foo* %0, i32 0, i32 0, !dbg !62
store i32 12, i32* %2, align 4, !dbg !62
%3 = getelementptr inbounds %Foo, %Foo* %0, i32 0, i32 1, !dbg !64
%4 = load i1, i1* %c, align 1, !dbg !65
br i1 %4, label %Then, label %Else, !dbg !65
Then: ; preds = %Entry
call fastcc void @bar1(%Bar* sret %3), !dbg !66
br label %EndIf, !dbg !64
Else: ; preds = %Entry
call fastcc void @bar2(%Bar* sret %3), !dbg !67
br label %EndIf, !dbg !64
EndIf: ; preds = %Else, %Then
ret void, !dbg !68
}
define internal fastcc void @bar1(%Bar* nonnull sret) unnamed_addr #2 !dbg !69 {
Entry:
%1 = bitcast %Bar* %0 to i8*, !dbg !73
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Bar* @1 to i8*), i64 4, i1 false), !dbg !73
ret void, !dbg !73
}
define internal fastcc void @bar2(%Bar* nonnull sret) unnamed_addr #2 !dbg !75 {
Entry:
%1 = bitcast %Bar* %0 to i8*, !dbg !76
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Bar* @2 to i8*), i64 4, i1 false), !dbg !76
ret void, !dbg !76
}
!39 = !DILocalVariable(name: "static", scope: !40, file: !5, line: 2, type: !41)
!49 = !DILocalVariable(name: "runtime", scope: !40, file: !5, line: 6, type: !41)
```
---
BRANCH_TODO | 8 +-
src/all_types.hpp | 49 ++++++++----
src/analyze.cpp | 6 ++
src/analyze.hpp | 1 +
src/codegen.cpp | 73 +++++++++--------
src/ir.cpp | 236 +++++++++++++++++++++++++++++++++++++-----------------
src/ir_print.cpp | 40 +++++----
7 files changed, 270 insertions(+), 143 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index fc8a654772..843703e20b 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,8 +1,8 @@
Scratch pad for stuff to do before merging master
=================================================
- * struct initializations
- * function call parameters
+ * array initializations
+ * union initializations
* bitCast
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
@@ -25,7 +25,3 @@ inferred comptime
return ir_build_ref(irb, scope, value->source_node, value, false, false);
handle if with no else
-
-
-
-
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 0061b5999f..fbd788c9d9 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1957,6 +1957,7 @@ enum ScopeId {
ScopeIdCompTime,
ScopeIdCoroPrelude,
ScopeIdRuntime,
+ ScopeIdElide,
};
struct Scope {
@@ -1970,6 +1971,14 @@ struct Scope {
ScopeId id;
};
+// This scope, when activated, causes all the instructions in the scope to be omitted
+// from the generated code.
+struct ScopeElide {
+ Scope base;
+
+ bool activated;
+};
+
// This scope comes from global declarations or from
// declarations in a container declaration
// NodeTypeContainerDecl
@@ -2189,7 +2198,6 @@ enum IrInstructionId {
IrInstructionIdResizeSlice,
IrInstructionIdContainerInitList,
IrInstructionIdContainerInitFields,
- IrInstructionIdStructInit,
IrInstructionIdUnionInit,
IrInstructionIdUnreachable,
IrInstructionIdTypeOf,
@@ -2279,6 +2287,7 @@ enum IrInstructionId {
IrInstructionIdPtrType,
IrInstructionIdAlignCast,
IrInstructionIdImplicitCast,
+ IrInstructionIdResolveResult,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
@@ -2366,6 +2375,7 @@ struct IrInstructionCondBr {
IrBasicBlock *then_block;
IrBasicBlock *else_block;
IrInstruction *is_comptime;
+ ResultLoc *result_loc;
};
struct IrInstructionBr {
@@ -2646,20 +2656,6 @@ struct IrInstructionContainerInitFields {
IrInstructionContainerInitFieldsField *fields;
};
-struct IrInstructionStructInitField {
- IrInstruction *value;
- TypeStructField *type_struct_field;
-};
-
-struct IrInstructionStructInit {
- IrInstruction base;
-
- ZigType *struct_type;
- size_t field_count;
- IrInstructionStructInitField *fields;
- LLVMValueRef tmp_ptr;
-};
-
struct IrInstructionUnionInit {
IrInstruction base;
@@ -3581,13 +3577,22 @@ struct IrInstructionImplicitCast {
IrInstruction *target;
};
+struct IrInstructionResolveResult {
+ IrInstruction base;
+
+ ResultLoc *result_loc;
+ IrInstruction *ty;
+};
+
enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
ResultLocIdVar,
+ ResultLocIdField,
ResultLocIdReturn,
ResultLocIdPeer,
ResultLocIdPeerParent,
+ ResultLocIdInstruction,
};
struct ResultLoc {
@@ -3597,6 +3602,7 @@ struct ResultLoc {
IrInstruction *source_instruction;
IrInstruction *gen_instruction; // value to store to the result loc
ZigType *implicit_elem_type;
+ ScopeElide *scope_elide;
};
struct ResultLocNone {
@@ -3609,6 +3615,14 @@ struct ResultLocVar {
ZigVar *var;
};
+struct ResultLocField {
+ ResultLoc base;
+
+ ResultLoc *parent;
+ Buf *name;
+ IrInstruction *container_type;
+};
+
struct ResultLocReturn {
ResultLoc base;
};
@@ -3636,6 +3650,11 @@ struct ResultLocPeer {
IrSuspendPosition suspend_pos;
};
+// The result location is the source instruction
+struct ResultLocInstruction {
+ ResultLoc base;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 771e11e93f..6299ac6699 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -166,6 +166,12 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct
return &scope->base;
}
+ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent) {
+ ScopeElide *scope = allocate(1);
+ init_scope(g, &scope->base, ScopeIdElide, node, parent);
+ return scope;
+}
+
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeSuspend);
ScopeSuspend *scope = allocate(1);
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 57f1072355..2f3ec663da 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -121,6 +121,7 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
+ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent);
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index eecc2239db..4fa13c39a2 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -715,6 +715,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
case ScopeIdCompTime:
case ScopeIdCoroPrelude:
case ScopeIdRuntime:
+ case ScopeIdElide:
return get_di_scope(g, scope->parent);
}
zig_unreachable();
@@ -2383,7 +2384,6 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
- LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
ZigType *return_type = return_instruction->value->value.type;
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
@@ -2391,13 +2391,16 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
if (return_instruction->value->value.special != ConstValSpecialRuntime) {
// if it's comptime we have to do this but if it's runtime trust that
// result location mechanism took care of it.
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
}
LLVMBuildRetVoid(g->builder);
} else if (handle_is_ptr(return_type)) {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
LLVMBuildRet(g->builder, by_val_value);
} else {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
LLVMBuildRet(g->builder, value);
}
return nullptr;
@@ -5032,29 +5035,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
}
-static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
- for (size_t i = 0; i < instruction->field_count; i += 1) {
- IrInstructionStructInitField *field = &instruction->fields[i];
- TypeStructField *type_struct_field = field->type_struct_field;
- if (!type_has_bits(type_struct_field->type_entry))
- continue;
-
- LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)type_struct_field->gen_index, "");
- LLVMValueRef value = ir_llvm_value(g, field->value);
-
- uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
- uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field);
-
- ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
- false, false, PtrLenSingle, field_align_bytes,
- (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false);
-
- gen_assign_raw(g, field_ptr, ptr_type, value);
- }
- return instruction->tmp_ptr;
-}
-
static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
TypeUnionField *type_union_field = instruction->field;
@@ -5531,10 +5511,6 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
}
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
- if (!g->strip_debug_symbols) {
- set_debug_location(g, instruction);
- }
-
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdConst:
@@ -5609,6 +5585,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdEndExpr:
case IrInstructionIdAllocaGen:
case IrInstructionIdImplicitCast:
+ case IrInstructionIdResolveResult:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5705,8 +5682,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
case IrInstructionIdUnionTag:
return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
- case IrInstructionIdStructInit:
- return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
case IrInstructionIdUnionInit:
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
case IrInstructionIdPtrCastGen:
@@ -5791,6 +5766,34 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
+static bool scope_is_elided(Scope *scope) {
+ for (;;) {
+ switch (scope->id) {
+ case ScopeIdDecls:
+ case ScopeIdCompTime:
+ case ScopeIdCImport:
+ zig_unreachable();
+ case ScopeIdElide:
+ if (reinterpret_cast(scope)->activated)
+ return true;
+ // fallthrough
+ case ScopeIdBlock:
+ case ScopeIdDefer:
+ case ScopeIdDeferExpr:
+ case ScopeIdVarDecl:
+ case ScopeIdLoop:
+ case ScopeIdSuspend:
+ case ScopeIdCoroPrelude:
+ case ScopeIdRuntime:
+ scope = scope->parent;
+ continue;
+ case ScopeIdFnDef:
+ return false;
+ }
+ zig_unreachable();
+ }
+}
+
static void ir_render(CodeGen *g, ZigFn *fn_entry) {
assert(fn_entry);
@@ -5806,7 +5809,12 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
continue;
- instruction->llvm_value = ir_render_instruction(g, executable, instruction);
+ if (!scope_is_elided(instruction->scope)) {
+ if (!g->strip_debug_symbols) {
+ set_debug_location(g, instruction);
+ }
+ instruction->llvm_value = ir_render_instruction(g, executable, instruction);
+ }
}
current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
}
@@ -6891,9 +6899,6 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdContainerInitList) {
IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
slot = &container_init_list_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdStructInit) {
- IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction;
- slot = &struct_init_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdUnionInit) {
IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
slot = &union_init_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 7f5b7da6e1..d34630554c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -616,10 +616,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
return IrInstructionIdRef;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {
- return IrInstructionIdStructInit;
-}
-
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) {
return IrInstructionIdUnionInit;
}
@@ -888,6 +884,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *)
return IrInstructionIdImplicitCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *) {
+ return IrInstructionIdResolveResult;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
return IrInstructionIdOpaqueType;
}
@@ -1517,20 +1517,6 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
return &container_init_fields_instruction->base;
}
-static IrInstruction *ir_build_struct_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigType *struct_type, size_t field_count, IrInstructionStructInitField *fields)
-{
- IrInstructionStructInit *struct_init_instruction = ir_build_instruction(irb, scope, source_node);
- struct_init_instruction->struct_type = struct_type;
- struct_init_instruction->field_count = field_count;
- struct_init_instruction->fields = fields;
-
- for (size_t i = 0; i < field_count; i += 1)
- ir_ref_instruction(fields[i].value, irb->current_basic_block);
-
- return &struct_init_instruction->base;
-}
-
static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
{
@@ -2764,6 +2750,18 @@ static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNo
return &instruction->base;
}
+static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc, IrInstruction *ty)
+{
+ IrInstructionResolveResult *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+ instruction->ty = ty;
+
+ ir_ref_instruction(ty, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionOpaqueType *instruction = ir_build_instruction(irb, scope, source_node);
@@ -3220,6 +3218,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco
case ScopeIdSuspend:
case ScopeIdCompTime:
case ScopeIdRuntime:
+ case ScopeIdElide:
scope = scope->parent;
continue;
case ScopeIdDeferExpr:
@@ -3276,6 +3275,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
case ScopeIdSuspend:
case ScopeIdCompTime:
case ScopeIdRuntime:
+ case ScopeIdElide:
scope = scope->parent;
continue;
case ScopeIdDeferExpr:
@@ -5549,7 +5549,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
zig_unreachable();
}
-static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeContainerInitExpr);
AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
@@ -5559,39 +5561,61 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
if (container_type == irb->codegen->invalid_instruction)
return container_type;
- if (kind == ContainerInitKindStruct) {
- size_t field_count = container_init_expr->entries.length;
- IrInstructionContainerInitFieldsField *fields = allocate(field_count);
- for (size_t i = 0; i < field_count; i += 1) {
- AstNode *entry_node = container_init_expr->entries.at(i);
- assert(entry_node->type == NodeTypeStructValueField);
-
- Buf *name = entry_node->data.struct_val_field.name;
- AstNode *expr_node = entry_node->data.struct_val_field.expr;
- IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
- if (expr_value == irb->codegen->invalid_instruction)
- return expr_value;
-
- fields[i].name = name;
- fields[i].value = expr_value;
- fields[i].source_node = entry_node;
- }
- return ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields);
- } else if (kind == ContainerInitKindArray) {
- size_t item_count = container_init_expr->entries.length;
- IrInstruction **values = allocate(item_count);
- for (size_t i = 0; i < item_count; i += 1) {
- AstNode *expr_node = container_init_expr->entries.at(i);
- IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
- if (expr_value == irb->codegen->invalid_instruction)
- return expr_value;
-
- values[i] = expr_value;
- }
- return ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
- } else {
- zig_unreachable();
+ switch (kind) {
+ case ContainerInitKindStruct: {
+ src_assert(result_loc->scope_elide == nullptr, node);
+ result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
+ size_t field_count = container_init_expr->entries.length;
+ IrInstructionContainerInitFieldsField *fields = allocate(field_count);
+ for (size_t i = 0; i < field_count; i += 1) {
+ AstNode *entry_node = container_init_expr->entries.at(i);
+ assert(entry_node->type == NodeTypeStructValueField);
+
+ Buf *name = entry_node->data.struct_val_field.name;
+ AstNode *expr_node = entry_node->data.struct_val_field.expr;
+
+ ResultLoc *child_result_loc = nullptr;
+ if (result_loc != nullptr) {
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
+ expr_node, result_loc, container_type);
+ IrInstruction *field_ptr = ir_build_field_ptr(irb, &result_loc->scope_elide->base, expr_node,
+ container_ptr, name);
+ ResultLocInstruction *result_loc_inst = allocate(1);
+ result_loc_inst->base.id = ResultLocIdInstruction;
+ result_loc_inst->base.source_instruction = field_ptr;
+ ir_ref_instruction(field_ptr, irb->current_basic_block);
+ child_result_loc = &result_loc_inst->base;
+ }
+
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, &result_loc->scope_elide->base,
+ LValNone, child_result_loc);
+ if (expr_value == irb->codegen->invalid_instruction)
+ return expr_value;
+
+ fields[i].name = name;
+ fields[i].value = expr_value;
+ fields[i].source_node = entry_node;
+ }
+ IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields);
+
+ return ir_lval_wrap(irb, scope, init_fields, lval, result_loc);
+ }
+ case ContainerInitKindArray: {
+ size_t item_count = container_init_expr->entries.length;
+ IrInstruction **values = allocate(item_count);
+ for (size_t i = 0; i < item_count; i += 1) {
+ AstNode *expr_node = container_init_expr->entries.at(i);
+ IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
+ if (expr_value == irb->codegen->invalid_instruction)
+ return expr_value;
+
+ values[i] = expr_value;
+ }
+ IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
+ return ir_lval_wrap(irb, scope, init_list, lval, result_loc);
+ }
}
+ zig_unreachable();
}
static ResultLocVar *create_var_result_loc(IrInstruction *alloca, ZigVar *var) {
@@ -7885,7 +7909,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypePrefixOpExpr:
return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc);
case NodeTypeContainerInitExpr:
- return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval, result_loc);
+ return ir_gen_container_init_expr(irb, scope, node, lval, result_loc);
case NodeTypeVariableDeclaration:
return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc);
case NodeTypeWhileExpr:
@@ -14468,7 +14492,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
return &result->base;
}
-static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_loc) {
+static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc)
+{
switch (result_loc->id) {
case ResultLocIdInvalid:
case ResultLocIdPeerParent:
@@ -14476,6 +14502,30 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_lo
case ResultLocIdNone:
case ResultLocIdVar:
return nullptr;
+ case ResultLocIdInstruction:
+ return result_loc->source_instruction->child->value.type;
+ case ResultLocIdField: {
+ if (result_loc->resolved_loc != nullptr) {
+ ZigType *ptr_type = result_loc->resolved_loc->value.type;
+ assert(ptr_type->id == ZigTypeIdPointer);
+ return ptr_type->data.pointer.child_type;
+ }
+ ResultLocField *result_loc_field = reinterpret_cast(result_loc);
+ ZigType *container_type = ir_resolve_type(ira, result_loc_field->container_type->child);
+ if (type_is_invalid(container_type))
+ return ira->codegen->builtin_types.entry_invalid;
+ if (container_type->id == ZigTypeIdStruct) {
+ TypeStructField *field = find_struct_type_field(container_type, result_loc_field->name);
+ if (field == nullptr) {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ return field->type_entry;
+ } else if (container_type->id == ZigTypeIdUnion) {
+ zig_panic("TODO");
+ } else {
+ zig_unreachable();
+ }
+ }
case ResultLocIdReturn:
return ira->explicit_return_type;
case ResultLocIdPeer:
@@ -14491,7 +14541,10 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
ResultLoc *result_loc, ZigType *value_type, IrInstruction *value)
{
if (result_loc->resolved_loc != nullptr) {
- return result_loc->resolved_loc;
+ // allow to redo the result location if the value is known and comptime and the previous one isn't
+ if (value == nullptr || !instr_is_comptime(value) || instr_is_comptime(result_loc->resolved_loc)) {
+ return result_loc->resolved_loc;
+ }
}
result_loc->gen_instruction = value;
result_loc->implicit_elem_type = value_type;
@@ -14524,7 +14577,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
return ira->codegen->invalid_instruction;
bool is_comptime = force_comptime || (value != nullptr &&
value->value.special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const);
- if (alloca_src->base.child == nullptr) {
+ if (alloca_src->base.child == nullptr || is_comptime) {
uint32_t align = 0;
if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
return ira->codegen->invalid_instruction;
@@ -14539,12 +14592,40 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align,
alloca_src->name_hint, force_comptime);
}
+ if (alloca_src->base.child != nullptr) {
+ alloca_src->base.child->ref_count = 0;
+ }
alloca_src->base.child = alloca_gen;
}
result_loc->written = true;
result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child;
return result_loc->resolved_loc;
}
+ case ResultLocIdInstruction: {
+ result_loc->written = true;
+ result_loc->resolved_loc = result_loc->source_instruction->child;
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdField: {
+ ResultLocField *result_loc_field = reinterpret_cast(result_loc);
+
+ ZigType *container_type = ir_resolve_type(ira, result_loc_field->container_type->child);
+ if (type_is_invalid(container_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr,
+ result_loc_field->parent, container_type, nullptr);
+ if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
+ parent_result_loc->value.type->id == ZigTypeIdUnreachable)
+ {
+ return parent_result_loc;
+ }
+
+ result_loc->written = true;
+ result_loc->resolved_loc = ir_analyze_container_field_ptr(ira, result_loc_field->name,
+ suspend_source_instr, parent_result_loc, container_type);
+ return result_loc->resolved_loc;
+ }
case ResultLocIdReturn: {
bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
if (is_comptime) return nullptr;
@@ -14593,7 +14674,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
ira->resume_stack.append(opposite_peer->suspend_pos);
}
}
- ZigType *expected_type = ir_result_loc_expected_type(ira, peer_parent->parent);
+ ZigType *expected_type = ir_result_loc_expected_type(ira, suspend_source_instr, peer_parent->parent);
peer_parent->resolved_type = ir_resolve_peer_types(ira,
peer_parent->base.source_instruction->source_node, expected_type, instructions,
peer_parent->peer_count);
@@ -14626,6 +14707,12 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns
return ir_implicit_cast(ira, target, dest_type);
}
+static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
+ ZigType *ty = ir_resolve_type(ira, instruction->ty->child);
+ if (type_is_invalid(ty))
+ return ira->codegen->invalid_instruction;
+ return ir_resolve_result(ira, &instruction->base, instruction->result_loc, ty, nullptr);
+}
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
@@ -18330,8 +18417,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
AstNode **field_assign_nodes = allocate(actual_field_count);
- IrInstructionStructInitField *new_fields = allocate(actual_field_count);
-
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
|| type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
@@ -18371,9 +18456,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
}
field_assign_nodes[field_index] = field->source_node;
- new_fields[field_index].value = casted_field_value;
- new_fields[field_index].type_struct_field = type_field;
-
if (const_val.special == ConstValSpecialStatic) {
if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
@@ -18416,9 +18498,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
copy_const_val(&runtime_inst->value, field->init_val, true);
- new_fields[i].value = runtime_inst;
- new_fields[i].type_struct_field = field;
-
if (const_val.special == ConstValSpecialStatic) {
copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);
}
@@ -18451,12 +18530,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
return ira->codegen->invalid_instruction;
}
- IrInstruction *new_instruction = ir_build_struct_init(&ira->new_irb,
- instruction->scope, instruction->source_node,
- container_type, actual_field_count, new_fields);
- new_instruction->value.type = container_type;
- ir_add_alloca(ira, new_instruction, container_type);
- return new_instruction;
+ // this instruction should not get to codegen
+ IrInstruction *result = ir_const(ira, instruction, container_type);
+ // this is how we signal to EndExpr the value is not comptime known
+ result->value.special = ConstValSpecialRuntime;
+ return result;
}
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
@@ -23794,7 +23872,18 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
- if (!instruction->result_loc->written) {
+ bool want_resolve_result = instruction->result_loc->written;
+ if (instruction->result_loc->written) {
+ if (instruction->result_loc->scope_elide != nullptr && instr_is_comptime(value)) {
+ want_resolve_result = true;
+ instruction->result_loc->scope_elide->activated = true;
+ } else {
+ want_resolve_result = false;
+ }
+ } else {
+ want_resolve_result = true;
+ }
+ if (want_resolve_result) {
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
value->value.type, value);
if (result_loc != nullptr) {
@@ -23815,7 +23904,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdWidenOrShorten:
- case IrInstructionIdStructInit:
case IrInstructionIdUnionInit:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdUnionFieldPtr:
@@ -24036,6 +24124,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
case IrInstructionIdImplicitCast:
return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
+ case IrInstructionIdResolveResult:
+ return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
case IrInstructionIdOpaqueType:
return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
case IrInstructionIdSetAlignStack:
@@ -24260,7 +24350,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
- case IrInstructionIdStructInit:
case IrInstructionIdUnionInit:
case IrInstructionIdFieldPtr:
case IrInstructionIdElemPtr:
@@ -24326,6 +24415,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTypeId:
case IrInstructionIdAlignCast:
case IrInstructionIdImplicitCast:
+ case IrInstructionIdResolveResult:
case IrInstructionIdOpaqueType:
case IrInstructionIdArgType:
case IrInstructionIdTagType:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 7d56b157d5..0f80a9b9e3 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -207,6 +207,18 @@ static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var)
fprintf(irp->f, ")");
}
+static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *result_loc_inst) {
+ fprintf(irp->f, "inst(");
+ ir_print_other_instruction(irp, result_loc_inst->base.source_instruction);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_result_loc_field(IrPrint *irp, ResultLocField *result_loc_field) {
+ fprintf(irp->f, "field(name=%s,type=", buf_ptr(result_loc_field->name));
+ ir_print_other_instruction(irp, result_loc_field->container_type);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_peer) {
fprintf(irp->f, "peer(next=");
ir_print_other_block(irp, result_loc_peer->next_bb);
@@ -225,6 +237,10 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
return;
case ResultLocIdVar:
return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
+ case ResultLocIdInstruction:
+ return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc);
+ case ResultLocIdField:
+ return ir_print_result_loc_field(irp, (ResultLocField *)result_loc);
case ResultLocIdPeer:
return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
case ResultLocIdPeerParent:
@@ -352,18 +368,6 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
fprintf(irp->f, "} // container init");
}
-static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) {
- fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name));
- for (size_t i = 0; i < instruction->field_count; i += 1) {
- IrInstructionStructInitField *field = &instruction->fields[i];
- Buf *field_name = field->type_struct_field->name;
- const char *comma = (i == 0) ? "" : ", ";
- fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name));
- ir_print_other_instruction(irp, field->value);
- }
- fprintf(irp->f, "} // struct init");
-}
-
static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
Buf *field_name = instruction->field->enum_field->name;
@@ -1265,6 +1269,12 @@ static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *inst
fprintf(irp->f, ")");
}
+static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) {
+ fprintf(irp->f, "ResolveResult(");
+ ir_print_result_loc(irp, instruction->result_loc);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
fprintf(irp->f, "@OpaqueType()");
}
@@ -1588,9 +1598,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdContainerInitFields:
ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
break;
- case IrInstructionIdStructInit:
- ir_print_struct_init(irp, (IrInstructionStructInit *)instruction);
- break;
case IrInstructionIdUnionInit:
ir_print_union_init(irp, (IrInstructionUnionInit *)instruction);
break;
@@ -1900,6 +1907,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdImplicitCast:
ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction);
break;
+ case IrInstructionIdResolveResult:
+ ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
+ break;
case IrInstructionIdOpaqueType:
ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
break;
--
cgit v1.2.3
From 4e2b2822f18577edb614bdc3ec6808a0587662e5 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 9 Jun 2019 19:55:15 -0400
Subject: inferred array size of array literals works
---
src/codegen.cpp | 27 +--------------------------
src/ir.cpp | 35 ++++++++++++++---------------------
2 files changed, 15 insertions(+), 47 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 763e1e1c50..b28f041391 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5072,30 +5072,6 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
return instruction->tmp_ptr;
}
-static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *executable,
- IrInstructionContainerInitList *instruction)
-{
- ZigType *array_type = instruction->base.value.type;
- assert(array_type->id == ZigTypeIdArray);
- LLVMValueRef tmp_array_ptr = instruction->tmp_ptr;
- assert(tmp_array_ptr);
-
- size_t field_count = instruction->item_count;
-
- ZigType *child_type = array_type->data.array.child_type;
- for (size_t i = 0; i < field_count; i += 1) {
- LLVMValueRef elem_val = ir_llvm_value(g, instruction->items[i]);
- LLVMValueRef indices[] = {
- LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
- LLVMConstInt(g->builtin_types.entry_usize->llvm_type, i, false),
- };
- LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
- gen_assign_raw(g, elem_ptr, get_pointer_to_type(g, child_type, false), elem_val);
- }
-
- return tmp_array_ptr;
-}
-
static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));
return nullptr;
@@ -5586,6 +5562,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdAllocaGen:
case IrInstructionIdImplicitCast:
case IrInstructionIdResolveResult:
+ case IrInstructionIdContainerInitList:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5700,8 +5677,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_int_to_err(g, executable, (IrInstructionIntToErr *)instruction);
case IrInstructionIdErrToInt:
return ir_render_err_to_int(g, executable, (IrInstructionErrToInt *)instruction);
- case IrInstructionIdContainerInitList:
- return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
case IrInstructionIdPanic:
return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);
case IrInstructionIdTagName:
diff --git a/src/ir.cpp b/src/ir.cpp
index 84c7dc6342..b29af2a1e2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1484,17 +1484,15 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
}
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_type, IrInstruction *elem_type, size_t item_count, IrInstruction **items)
+ IrInstruction *container_type, size_t item_count, IrInstruction **items)
{
IrInstructionContainerInitList *container_init_list_instruction =
ir_build_instruction(irb, scope, source_node);
container_init_list_instruction->container_type = container_type;
- container_init_list_instruction->elem_type = elem_type;
container_init_list_instruction->item_count = item_count;
container_init_list_instruction->items = items;
- if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
- if (elem_type != nullptr) ir_ref_instruction(elem_type, irb->current_basic_block);
+ ir_ref_instruction(container_type, irb->current_basic_block);
for (size_t i = 0; i < item_count; i += 1) {
ir_ref_instruction(items[i], irb->current_basic_block);
}
@@ -5620,11 +5618,17 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
src_assert(result_loc->scope_elide == nullptr, node);
result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
+ size_t item_count = container_init_expr->entries.length;
+
+ if (container_type == nullptr) {
+ IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
+ container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
+ }
+
src_assert(result_loc != nullptr, node);
IrInstruction *container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
node, result_loc, container_type);
- size_t item_count = container_init_expr->entries.length;
IrInstruction **values = allocate(item_count);
for (size_t i = 0; i < item_count; i += 1) {
AstNode *expr_node = container_init_expr->entries.at(i);
@@ -5644,7 +5648,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
values[i] = expr_value;
}
- IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, elem_type,
+ IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
item_count, values);
return ir_lval_wrap(irb, scope, init_list, lval, result_loc);
}
@@ -18538,22 +18542,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
{
Error err;
- size_t elem_count = instruction->item_count;
+ ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
+ if (type_is_invalid(container_type))
+ return ira->codegen->invalid_instruction;
- ZigType *container_type;
- if (instruction->container_type != nullptr) {
- container_type = ir_resolve_type(ira, instruction->container_type->child);
- if (type_is_invalid(container_type))
- return ira->codegen->invalid_instruction;
- } else {
- ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
- if (type_is_invalid(elem_type))
- return ira->codegen->invalid_instruction;
- if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) {
- return ira->codegen->invalid_instruction;
- }
- container_type = get_array_type(ira->codegen, elem_type, elem_count);
- }
+ size_t elem_count = instruction->item_count;
if (is_slice(container_type)) {
ir_add_error(ira, &instruction->base,
--
cgit v1.2.3
From 1a51bf63047e9a3cd6ae3273296fded82009235c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 11:15:32 -0400
Subject: hook up result locations for union initializations
```zig
export fn entry() void {
var x = Foo{ .bar = bar() };
}
```
```llvm
define void @entry() #2 !dbg !44 {
Entry:
%x = alloca %Foo, align 4
%0 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 1, !dbg !68
store i1 true, i1* %0, align 1, !dbg !68
%1 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0, !dbg !68
%2 = bitcast { i32, [4 x i8] }* %1 to %Bar*, !dbg !68
call fastcc void @bar(%Bar* sret %2), !dbg !68
call void @llvm.dbg.declare(metadata %Foo* %x, metadata !48, metadata !DIExpression()), !dbg !69
ret void, !dbg !70
}
```
---
BRANCH_TODO | 1 -
src/all_types.hpp | 13 +------
src/codegen.cpp | 49 +++---------------------
src/ir.cpp | 109 ++++++++++++++++++++++++------------------------------
src/ir_print.cpp | 12 ------
5 files changed, 56 insertions(+), 128 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index df4375ad7d..2744901bfa 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,7 +1,6 @@
Scratch pad for stuff to do before merging master
=================================================
- * union initializations
* bitCast
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 703ff5aea1..35e9786baa 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2204,7 +2204,6 @@ enum IrInstructionId {
IrInstructionIdResizeSlice,
IrInstructionIdContainerInitList,
IrInstructionIdContainerInitFields,
- IrInstructionIdUnionInit,
IrInstructionIdUnreachable,
IrInstructionIdTypeOf,
IrInstructionIdSetCold,
@@ -2520,6 +2519,7 @@ struct IrInstructionStorePtr {
struct IrInstructionFieldPtr {
IrInstruction base;
+ bool initializing;
IrInstruction *container_ptr;
Buf *field_name_buffer;
IrInstruction *field_name_expr;
@@ -2536,9 +2536,9 @@ struct IrInstructionStructFieldPtr {
struct IrInstructionUnionFieldPtr {
IrInstruction base;
+ bool initializing;
IrInstruction *union_ptr;
TypeUnionField *field;
- bool is_const;
};
struct IrInstructionElemPtr {
@@ -2663,15 +2663,6 @@ struct IrInstructionContainerInitFields {
IrInstructionContainerInitFieldsField *fields;
};
-struct IrInstructionUnionInit {
- IrInstruction base;
-
- ZigType *union_type;
- TypeUnionField *field;
- IrInstruction *init_value;
- LLVMValueRef tmp_ptr;
-};
-
struct IrInstructionUnreachable {
IrInstruction base;
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index b28f041391..eb2e92f627 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3859,7 +3859,12 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
return bitcasted_union_field_ptr;
}
- if (ir_want_runtime_safety(g, &instruction->base)) {
+ if (instruction->initializing) {
+ LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
+ LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
+ &field->enum_field->value);
+ gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
+ } else if (ir_want_runtime_safety(g, &instruction->base)) {
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
@@ -5035,43 +5040,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
}
-static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
- TypeUnionField *type_union_field = instruction->field;
-
- if (!type_has_bits(type_union_field->type_entry))
- return nullptr;
-
- uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
- ZigType *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
- false, false, PtrLenSingle, field_align_bytes,
- 0, 0, false);
-
- LLVMValueRef uncasted_union_ptr;
- // Even if safety is off in this block, if the union type has the safety field, we have to populate it
- // correctly. Otherwise safety code somewhere other than here could fail.
- ZigType *union_type = instruction->union_type;
- if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
- LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- union_type->data.unionation.gen_tag_index, "");
-
- LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
- &type_union_field->enum_field->value);
- gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
-
- uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)union_type->data.unionation.gen_union_index, "");
- } else {
- uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, "");
- }
-
- LLVMValueRef field_ptr = LLVMBuildBitCast(g->builder, uncasted_union_ptr, get_llvm_type(g, ptr_type), "");
- LLVMValueRef value = ir_llvm_value(g, instruction->init_value);
-
- gen_assign_raw(g, field_ptr, ptr_type, value);
-
- return instruction->tmp_ptr;
-}
-
static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));
return nullptr;
@@ -5659,8 +5627,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
case IrInstructionIdUnionTag:
return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
- case IrInstructionIdUnionInit:
- return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
case IrInstructionIdPtrCastGen:
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
case IrInstructionIdBitCastGen:
@@ -6874,9 +6840,6 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdContainerInitList) {
IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
slot = &container_init_list_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdUnionInit) {
- IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
- slot = &union_init_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdSlice) {
IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
slot = &slice_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index b29af2a1e2..05f95a2480 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -164,7 +164,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
- IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
+ IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing);
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);
static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc);
@@ -616,10 +616,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
return IrInstructionIdRef;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) {
- return IrInstructionIdUnionInit;
-}
-
static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {
return IrInstructionIdCompileErr;
}
@@ -1312,12 +1308,13 @@ static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scop
}
static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_ptr, Buf *field_name)
+ IrInstruction *container_ptr, Buf *field_name, bool initializing)
{
IrInstructionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node);
instruction->container_ptr = container_ptr;
instruction->field_name_buffer = field_name;
instruction->field_name_expr = nullptr;
+ instruction->initializing = initializing;
ir_ref_instruction(container_ptr, irb->current_basic_block);
@@ -1337,9 +1334,10 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As
}
static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *union_ptr, TypeUnionField *field)
+ IrInstruction *union_ptr, TypeUnionField *field, bool initializing)
{
IrInstructionUnionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->initializing = initializing;
instruction->union_ptr = union_ptr;
instruction->field = field;
@@ -1517,19 +1515,6 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
return &container_init_fields_instruction->base;
}
-static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
-{
- IrInstructionUnionInit *union_init_instruction = ir_build_instruction(irb, scope, source_node);
- union_init_instruction->union_type = union_type;
- union_init_instruction->field = field;
- union_init_instruction->init_value = init_value;
-
- ir_ref_instruction(init_value, irb->current_basic_block);
-
- return &union_init_instruction->base;
-}
-
static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionUnreachable *unreachable_instruction =
ir_build_instruction(irb, scope, source_node);
@@ -4121,7 +4106,7 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode
if (container_ref_instruction == irb->codegen->invalid_instruction)
return container_ref_instruction;
- return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name);
+ return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false);
}
static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *node, IrOverflowOp op) {
@@ -5594,7 +5579,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
AstNode *expr_node = entry_node->data.struct_val_field.expr;
IrInstruction *field_ptr = ir_build_field_ptr(irb, &result_loc->scope_elide->base, expr_node,
- container_ptr, name);
+ container_ptr, name, true);
ResultLocInstruction *result_loc_inst = allocate(1);
result_loc_inst->base.id = ResultLocIdInstruction;
result_loc_inst->base.source_instruction = field_ptr;
@@ -6105,7 +6090,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
IrBasicBlock *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue");
Buf *len_field_name = buf_create_from_str("len");
- IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name);
+ IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false);
IrInstruction *len_val = ir_build_load_ptr(irb, parent_scope, node, len_ref);
ir_build_br(irb, parent_scope, node, cond_block, is_comptime);
@@ -7496,7 +7481,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
// set the is_canceled bit
IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
@@ -7575,7 +7560,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
// clear the is_suspended bit
IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
@@ -7642,12 +7627,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, target_inst);
Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
- IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
+ IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name, false);
if (irb->codegen->have_err_ret_tracing) {
IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
- IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
+ IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name, false);
ir_build_store_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
}
@@ -7669,7 +7654,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise);
IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);
@@ -7723,12 +7708,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
if (irb->codegen->have_err_ret_tracing) {
Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
- IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
+ IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name, false);
IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
}
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
- IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
+ IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name, false);
// If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
// because we're about to destroy the memory. So we store it into our result variable.
IrInstruction *no_suspend_result = ir_build_load_ptr(irb, scope, node, promise_result_ptr);
@@ -8152,7 +8137,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
build_decl_var_and_init(irb, coro_scope, node, irb->exec->coro_allocator_var, implicit_allocator_ptr,
"allocator", const_bool_false);
Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
- IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name);
+ IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name, false);
IrInstruction *realloc_fn = ir_build_load_ptr(irb, coro_scope, node, realloc_fn_ptr);
IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, realloc_fn, coro_size);
IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);
@@ -8172,30 +8157,30 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
irb->exec->atomic_state_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
- atomic_state_field_name);
+ atomic_state_field_name, false);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
ir_build_store_ptr(irb, scope, node, irb->exec->atomic_state_field_ptr, zero);
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
- irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
+ irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name, false);
result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
- irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
+ irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name, false);
ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
if (irb->codegen->have_err_ret_tracing) {
// initialize the error return trace
Buf *return_addresses_field_name = buf_create_from_str(RETURN_ADDRESSES_FIELD_NAME);
- IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);
+ IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name, false);
Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
- err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
+ err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name, false);
ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);
// coordinate with builtin.zig
Buf *index_name = buf_create_from_str("index");
- IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name);
+ IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name, false);
ir_build_store_ptr(irb, scope, node, index_ptr, zero);
Buf *instruction_addresses_name = buf_create_from_str("instruction_addresses");
- IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name);
+ IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name, false);
IrInstruction *slice_value = ir_build_slice(irb, scope, node, return_addresses_ptr, zero, nullptr, false);
ir_build_store_ptr(irb, scope, node, addrs_slice_ptr, slice_value);
@@ -8256,7 +8241,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
}
if (irb->codegen->have_err_ret_tracing) {
Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
- IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
+ IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name, false);
IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);
ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);
}
@@ -8291,7 +8276,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
Buf *shrink_field_name = buf_create_from_str(ASYNC_SHRINK_FIELD_NAME);
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
ImplicitAllocatorIdLocalVar);
- IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name);
+ IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name, false);
IrInstruction *shrink_fn = ir_build_load_ptr(irb, scope, node, shrink_fn_ptr);
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
@@ -14722,7 +14707,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
ir_assert(async_allocator_inst->value.type->id == ZigTypeIdPointer, &call_instruction->base);
ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,
- async_allocator_inst, container_type);
+ async_allocator_inst, container_type, false);
if (type_is_invalid(field_ptr_inst->value.type)) {
return ira->codegen->invalid_instruction;
}
@@ -16580,7 +16565,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
}
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
- IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type)
+ IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
{
Error err;
@@ -16664,15 +16649,19 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
if (type_is_invalid(union_val->type))
return ira->codegen->invalid_instruction;
- TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
- if (actual_field == nullptr)
- zig_unreachable();
+ if (initializing) {
+ bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
+ } else {
+ TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
+ if (actual_field == nullptr)
+ zig_unreachable();
- if (field != actual_field) {
- ir_add_error_node(ira, source_instr->source_node,
- buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name),
- buf_ptr(actual_field->name)));
- return ira->codegen->invalid_instruction;
+ if (field != actual_field) {
+ ir_add_error_node(ira, source_instr->source_node,
+ buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name),
+ buf_ptr(actual_field->name)));
+ return ira->codegen->invalid_instruction;
+ }
}
ConstExprValue *payload_val = union_val->data.x_union.payload;
@@ -16690,7 +16679,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
}
}
- IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
+ IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, container_ptr, field, initializing);
result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
PtrLenSingle, 0, 0, 0, false);
return result;
@@ -16826,10 +16816,10 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (container_type->id == ZigTypeIdPointer) {
ZigType *bare_type = container_ref_type(container_type);
IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);
- IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type);
+ IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type, field_ptr_instruction->initializing);
return result;
} else {
- IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type);
+ IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type, field_ptr_instruction->initializing);
return result;
}
} else if (is_array_ref(container_type)) {
@@ -18120,7 +18110,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
}
IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, target_value_ptr, field);
+ instruction->base.scope, instruction->base.source_node, target_value_ptr, field, false);
result->value.type = get_pointer_to_type(ira->codegen, field->type_entry,
target_value_ptr->value.type->data.pointer.is_const);
return result;
@@ -18386,11 +18376,10 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
return result;
}
- IrInstruction *new_instruction = ir_build_union_init(&ira->new_irb,
- instruction->scope, instruction->source_node,
- container_type, type_field, casted_field_value);
- new_instruction->value.type = container_type;
- ir_add_alloca(ira, new_instruction, container_type);
+ // this instruction should not get to codegen
+ IrInstruction *new_instruction = ir_const(ira, instruction, container_type);
+ // this is how we signal to EndExpr the value is not comptime known
+ new_instruction->value.special = ConstValSpecialRuntime;
return new_instruction;
}
@@ -23907,7 +23896,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdWidenOrShorten:
- case IrInstructionIdUnionInit:
case IrInstructionIdStructFieldPtr:
case IrInstructionIdUnionFieldPtr:
case IrInstructionIdOptionalWrap:
@@ -24353,7 +24341,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
- case IrInstructionIdUnionInit:
case IrInstructionIdFieldPtr:
case IrInstructionIdElemPtr:
case IrInstructionIdVarPtr:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 9181f66be5..42b93aec4e 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -360,15 +360,6 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
fprintf(irp->f, "} // container init");
}
-static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
- Buf *field_name = instruction->field->enum_field->name;
-
- fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
- fprintf(irp->f, ".%s = ", buf_ptr(field_name));
- ir_print_other_instruction(irp, instruction->init_value);
- fprintf(irp->f, "} // union init");
-}
-
static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
fprintf(irp->f, "unreachable");
}
@@ -1590,9 +1581,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdContainerInitFields:
ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
break;
- case IrInstructionIdUnionInit:
- ir_print_union_init(irp, (IrInstructionUnionInit *)instruction);
- break;
case IrInstructionIdUnreachable:
ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
break;
--
cgit v1.2.3
From 17b1ac5d03cd32e047d917a88e029c143cb5d119 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 12:24:19 -0400
Subject: result location semantics for `@bitCast`
```zig
export fn entry() void {
var x = @bitCast(f32, foo());
}
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%x = alloca float, align 4
%0 = bitcast float* %x to %Foo*, !dbg !42
call fastcc void @foo(%Foo* sret %0), !dbg !42
call void @llvm.dbg.declare(metadata float* %x, metadata !39, metadata !DIExpression()), !dbg !43
ret void, !dbg !44
}
```
---
BRANCH_TODO | 4 +-
src/all_types.hpp | 18 +++---
src/codegen.cpp | 14 +----
src/ir.cpp | 178 ++++++++++++++++++++++++++----------------------------
src/ir_print.cpp | 19 +++---
5 files changed, 103 insertions(+), 130 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 2744901bfa..296d8a24fd 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,8 +1,6 @@
Scratch pad for stuff to do before merging master
=================================================
- * bitCast
-
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
return ir_gen_comptime(irb, scope, node, lval);
@@ -23,3 +21,5 @@ inferred comptime
return ir_build_ref(irb, scope, value->source_node, value, false, false);
handle if with no else
+
+
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 35e9786baa..ef4d94880b 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2267,7 +2267,6 @@ enum IrInstructionId {
IrInstructionIdTestComptime,
IrInstructionIdPtrCastSrc,
IrInstructionIdPtrCastGen,
- IrInstructionIdBitCast,
IrInstructionIdBitCastGen,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
@@ -2645,7 +2644,6 @@ struct IrInstructionContainerInitList {
IrInstruction *elem_type;
size_t item_count;
IrInstruction **items;
- LLVMValueRef tmp_ptr;
};
struct IrInstructionContainerInitFieldsField {
@@ -3136,18 +3134,10 @@ struct IrInstructionPtrCastGen {
bool safety_check_on;
};
-struct IrInstructionBitCast {
- IrInstruction base;
-
- IrInstruction *dest_type;
- IrInstruction *value;
-};
-
struct IrInstructionBitCastGen {
IrInstruction base;
IrInstruction *operand;
- LLVMValueRef tmp_ptr;
};
struct IrInstructionWidenOrShorten {
@@ -3590,6 +3580,7 @@ enum ResultLocId {
ResultLocIdPeer,
ResultLocIdPeerParent,
ResultLocIdInstruction,
+ ResultLocIdBitCast,
};
struct ResultLoc {
@@ -3644,6 +3635,13 @@ struct ResultLocInstruction {
ResultLoc base;
};
+// The source_instruction is the destination type
+struct ResultLocBitCast {
+ ResultLoc base;
+
+ ResultLoc *parent;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index eb2e92f627..894d22d471 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3145,12 +3145,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
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(get_llvm_type(g, actual_type), 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;
+ zig_unreachable();
}
}
@@ -5520,7 +5515,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPtrCastSrc:
case IrInstructionIdCmpxchgSrc:
case IrInstructionIdLoadPtr:
- case IrInstructionIdBitCast:
case IrInstructionIdGlobalAsm:
case IrInstructionIdHasDecl:
case IrInstructionIdUndeclaredIdent:
@@ -6837,9 +6831,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdContainerInitList) {
- IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
- slot = &container_init_list_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdSlice) {
IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
slot = &slice_instruction->tmp_ptr;
@@ -6861,9 +6852,6 @@ 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 05f95a2480..26d0d59b28 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -780,10 +780,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
return IrInstructionIdPtrCastGen;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
- return IrInstructionIdBitCast;
-}
-
static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
return IrInstructionIdBitCastGen;
}
@@ -2429,20 +2425,6 @@ static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *sourc
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(
- irb, scope, source_node);
- instruction->dest_type = dest_type;
- instruction->value = value;
-
- 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)
{
@@ -4836,18 +4818,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
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 *dest_type_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope);
+ if (dest_type == irb->codegen->invalid_instruction)
+ return dest_type;
+
+ ResultLocBitCast *result_loc_bit_cast = allocate(1);
+ result_loc_bit_cast->base.id = ResultLocIdBitCast;
+ result_loc_bit_cast->base.source_instruction = dest_type;
+ result_loc_bit_cast->parent = result_loc;
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
+ IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone,
+ &result_loc_bit_cast->base);
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *bit_cast = ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, bit_cast, lval, result_loc);
+ return ir_lval_wrap(irb, scope, arg1_value, lval, result_loc);
}
case BuiltinFnIdIntToPtr:
{
@@ -14059,9 +14046,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
bool var_class_requires_const = false;
IrInstruction *var_ptr = decl_var_instruction->ptr->child;
- // if this assertion trips there may be a missing ir_expr_wrap in pass1 IR generation.
- ir_assert(var_ptr != nullptr, &decl_var_instruction->base);
- if (type_is_invalid(var_ptr->value.type)) {
+ // if this is null, a compiler error happened and did not initialize the variable.
+ // if there are no compile errors there may be a missing ir_expr_wrap in pass1 IR generation.
+ if (var_ptr == nullptr || type_is_invalid(var_ptr->value.type)) {
+ ir_assert(var_ptr != nullptr || ira->codegen->errors.length != 0, &decl_var_instruction->base);
var->var_type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->invalid_instruction;
}
@@ -14528,6 +14516,7 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspe
zig_unreachable();
case ResultLocIdNone:
case ResultLocIdVar:
+ case ResultLocIdBitCast:
return nullptr;
case ResultLocIdInstruction:
return result_loc->source_instruction->child->value.type;
@@ -14539,6 +14528,28 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspe
zig_unreachable();
}
+static bool type_can_bit_cast(ZigType *t) {
+ switch (t->id) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdMetaType:
+ case ZigTypeIdOpaque:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdUnreachable:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdEnumLiteral:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdPointer:
+ return false;
+ default:
+ // TODO list these types out explicitly, there are probably some other invalid ones here
+ return true;
+ }
+}
+
// give nullptr for value to resolve it at runtime
// returns a result location, or nullptr if the result location was already taken care of
// when calling this function, at the callsite must check for result type noreturn and propagate it up
@@ -14676,6 +14687,50 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
result_loc->resolved_loc = parent_result_loc;
return result_loc->resolved_loc;
}
+ case ResultLocIdBitCast: {
+ ResultLocBitCast *result_bit_cast = reinterpret_cast(result_loc);
+ ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->invalid_instruction;
+
+ if (get_codegen_ptr_type(dest_type) != nullptr) {
+ ir_add_error(ira, result_loc->source_instruction,
+ buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (!type_can_bit_cast(dest_type)) {
+ ir_add_error(ira, result_loc->source_instruction,
+ buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (get_codegen_ptr_type(value_type) != nullptr) {
+ ir_add_error(ira, suspend_source_instr,
+ buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (!type_can_bit_cast(value_type)) {
+ ir_add_error(ira, suspend_source_instr,
+ buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&value_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+
+ IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
+ dest_type, nullptr);
+ if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
+ parent_result_loc->value.type->id == ZigTypeIdUnreachable)
+ {
+ return parent_result_loc;
+ }
+ ZigType *ptr_type = get_pointer_to_type(ira->codegen, value_type, false);
+ result_loc->written = true;
+ result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
+ ptr_type, result_bit_cast->base.source_instruction, false);
+ return result_loc->resolved_loc;
+ }
}
zig_unreachable();
}
@@ -22755,28 +22810,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
zig_unreachable();
}
-static bool type_can_bit_cast(ZigType *t) {
- switch (t->id) {
- case ZigTypeIdInvalid:
- zig_unreachable();
- case ZigTypeIdMetaType:
- case ZigTypeIdOpaque:
- case ZigTypeIdBoundFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdUnreachable:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdEnumLiteral:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- case ZigTypeIdPointer:
- return false;
- default:
- // TODO list these types out explicitly, there are probably some other invalid ones here
- return true;
- }
-}
-
static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *dest_type)
{
@@ -22829,50 +22862,10 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
}
IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
- if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) {
- ir_add_alloca(ira, result, dest_type);
- }
+ assert(!(handle_is_ptr(dest_type) && !handle_is_ptr(src_type)));
return result;
}
-static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
- IrInstruction *dest_type_value = instruction->dest_type->child;
- ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
- if (type_is_invalid(dest_type))
- return ira->codegen->invalid_instruction;
-
- IrInstruction *value = instruction->value->child;
- ZigType *src_type = value->value.type;
- if (type_is_invalid(src_type))
- return ira->codegen->invalid_instruction;
-
- if (get_codegen_ptr_type(src_type) != nullptr) {
- ir_add_error(ira, value,
- buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if (!type_can_bit_cast(src_type)) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if (get_codegen_ptr_type(dest_type) != nullptr) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if (!type_can_bit_cast(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->invalid_instruction;
- }
-
- return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
-}
-
static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
ZigType *ptr_type)
{
@@ -24089,8 +24082,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
case IrInstructionIdPtrCastSrc:
return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)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 IrInstructionIdPtrToInt:
@@ -24386,7 +24377,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
case IrInstructionIdPtrCastGen:
- case IrInstructionIdBitCast:
case IrInstructionIdBitCastGen:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 42b93aec4e..925d802e6d 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -219,6 +219,12 @@ static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_pee
fprintf(irp->f, ")");
}
+static void ir_print_result_loc_bit_cast(IrPrint *irp, ResultLocBitCast *result_loc_bit_cast) {
+ fprintf(irp->f, "bitcast(ty=");
+ ir_print_other_instruction(irp, result_loc_bit_cast->base.source_instruction);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
switch (result_loc->id) {
case ResultLocIdInvalid:
@@ -235,6 +241,8 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc);
case ResultLocIdPeer:
return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
+ case ResultLocIdBitCast:
+ return ir_print_result_loc_bit_cast(irp, (ResultLocBitCast *)result_loc);
case ResultLocIdPeerParent:
fprintf(irp->f, "peer_parent");
return;
@@ -1011,14 +1019,6 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
fprintf(irp->f, ")");
}
-static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
- fprintf(irp->f, "@bitCast(");
- 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_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {
fprintf(irp->f, "@bitCast(");
ir_print_other_instruction(irp, instruction->operand);
@@ -1818,9 +1818,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdPtrCastGen:
ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
break;
- case IrInstructionIdBitCast:
- ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
- break;
case IrInstructionIdBitCastGen:
ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
break;
--
cgit v1.2.3
From c36289511629e01bbd32bc5f1133f5ed5997d1e0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 15:49:45 -0400
Subject: result location semantics for slices
```zig
export fn entry() void {
var buf: [10]u8 = undefined;
const slice1: []const u8 = &buf;
const slice2 = buf[0..];
}
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%buf = alloca [10 x i8], align 1
%slice1 = alloca %"[]u8", align 8
%slice2 = alloca %"[]u8", align 8
%0 = bitcast [10 x i8]* %buf to i8*, !dbg !46
call void @llvm.memset.p0i8.i64(i8* align 1 %0, i8 -86, i64 10, i1 false), !dbg !46
call void @llvm.dbg.declare(metadata [10 x i8]* %buf, metadata !39, metadata !DIExpression()), !dbg !46
%1 = getelementptr inbounds %"[]u8", %"[]u8"* %slice1, i32 0, i32 0, !dbg !47
%2 = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0, !dbg !47
store i8* %2, i8** %1, align 8, !dbg !47
%3 = getelementptr inbounds %"[]u8", %"[]u8"* %slice1, i32 0, i32 1, !dbg !47
store i64 10, i64* %3, align 8, !dbg !47
call void @llvm.dbg.declare(metadata %"[]u8"* %slice1, metadata !44, metadata !DIExpression()), !dbg !48
%4 = getelementptr inbounds %"[]u8", %"[]u8"* %slice2, i32 0, i32 0, !dbg !49
%5 = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0, !dbg !49
store i8* %5, i8** %4, align 8, !dbg !49
%6 = getelementptr inbounds %"[]u8", %"[]u8"* %slice2, i32 0, i32 1, !dbg !49
store i64 10, i64* %6, align 8, !dbg !49
call void @llvm.dbg.declare(metadata %"[]u8"* %slice2, metadata !45, metadata !DIExpression()), !dbg !50
ret void, !dbg !51
}
```
---
BRANCH_TODO | 3 -
src/all_types.hpp | 27 +++++++--
src/codegen.cpp | 72 ++++++++++++-----------
src/ir.cpp | 172 +++++++++++++++++++++++++++++++++++++-----------------
src/ir_print.cpp | 33 +++++++++--
5 files changed, 210 insertions(+), 97 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 296d8a24fd..e744162fa0 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -20,6 +20,3 @@ inferred comptime
// an instruction which just makes a pointer of it.
return ir_build_ref(irb, scope, value->source_node, value, false, false);
-handle if with no else
-
-
diff --git a/src/all_types.hpp b/src/all_types.hpp
index ef4d94880b..73580619ed 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2248,7 +2248,8 @@ enum IrInstructionId {
IrInstructionIdBoolNot,
IrInstructionIdMemset,
IrInstructionIdMemcpy,
- IrInstructionIdSlice,
+ IrInstructionIdSliceSrc,
+ IrInstructionIdSliceGen,
IrInstructionIdMemberCount,
IrInstructionIdMemberType,
IrInstructionIdMemberName,
@@ -2334,6 +2335,7 @@ enum IrInstructionId {
IrInstructionIdAllocaSrc,
IrInstructionIdAllocaGen,
IrInstructionIdEndExpr,
+ IrInstructionIdPtrOfArrayToSlice,
};
struct IrInstruction {
@@ -2617,7 +2619,6 @@ enum CastOp {
CastOpNumLitToConcrete,
CastOpErrSet,
CastOpBitCast,
- CastOpPtrOfArrayToSlice,
};
// TODO get rid of this instruction, replace with instructions for each op code
@@ -2989,14 +2990,24 @@ struct IrInstructionMemcpy {
IrInstruction *count;
};
-struct IrInstructionSlice {
+struct IrInstructionSliceSrc {
IrInstruction base;
+ bool safety_check_on;
IrInstruction *ptr;
IrInstruction *start;
IrInstruction *end;
+ ResultLoc *result_loc;
+};
+
+struct IrInstructionSliceGen {
+ IrInstruction base;
+
bool safety_check_on;
- LLVMValueRef tmp_ptr;
+ IrInstruction *ptr;
+ IrInstruction *start;
+ IrInstruction *end;
+ IrInstruction *result_loc;
};
struct IrInstructionMemberCount {
@@ -3563,6 +3574,7 @@ struct IrInstructionImplicitCast {
IrInstruction *dest_type;
IrInstruction *target;
+ ResultLoc *result_loc;
};
struct IrInstructionResolveResult {
@@ -3572,6 +3584,13 @@ struct IrInstructionResolveResult {
IrInstruction *ty;
};
+struct IrInstructionPtrOfArrayToSlice {
+ IrInstruction base;
+
+ IrInstruction *operand;
+ IrInstruction *result_loc;
+};
+
enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 894d22d471..f748c575b0 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3072,33 +3072,39 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
return expr_val;
case CastOpBitCast:
return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
- case CastOpPtrOfArrayToSlice: {
- assert(cast_instruction->tmp_ptr);
- assert(actual_type->id == ZigTypeIdPointer);
- ZigType *array_type = actual_type->data.pointer.child_type;
- assert(array_type->id == ZigTypeIdArray);
-
- LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- slice_ptr_index, "");
- LLVMValueRef indices[] = {
- LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
- LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
- };
- LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
- gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
-
- LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- slice_len_index, "");
- LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
- array_type->data.array.len, false);
- gen_store_untyped(g, len_value, len_field_ptr, 0, false);
-
- return cast_instruction->tmp_ptr;
- }
}
zig_unreachable();
}
+static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *executable,
+ IrInstructionPtrOfArrayToSlice *instruction)
+{
+ ZigType *actual_type = instruction->operand->value.type;
+ LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
+ assert(expr_val);
+
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+
+ assert(actual_type->id == ZigTypeIdPointer);
+ ZigType *array_type = actual_type->data.pointer.child_type;
+ assert(array_type->id == ZigTypeIdArray);
+
+ LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_ptr_index, "");
+ LLVMValueRef indices[] = {
+ LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
+ LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
+ };
+ LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
+ gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
+
+ LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_len_index, "");
+ LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
+ array_type->data.array.len, false);
+ gen_store_untyped(g, len_value, len_field_ptr, 0, false);
+
+ return result_loc;
+}
+
static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
IrInstructionPtrCastGen *instruction)
{
@@ -4603,16 +4609,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
return nullptr;
}
-static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) {
- assert(instruction->tmp_ptr);
-
+static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSliceGen *instruction) {
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);
ZigType *array_ptr_type = instruction->ptr->value.type;
assert(array_ptr_type->id == ZigTypeIdPointer);
ZigType *array_type = array_ptr_type->data.pointer.child_type;
LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
- LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
+ LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
@@ -4630,7 +4634,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
end_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false);
}
if (want_runtime_safety) {
- add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ if (instruction->start->value.special == ConstValSpecialRuntime || instruction->end) {
+ add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ }
if (instruction->end) {
LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
array_type->data.array.len, false);
@@ -5525,6 +5531,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdImplicitCast:
case IrInstructionIdResolveResult:
case IrInstructionIdContainerInitList:
+ case IrInstructionIdSliceSrc:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5595,8 +5602,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_memset(g, executable, (IrInstructionMemset *)instruction);
case IrInstructionIdMemcpy:
return ir_render_memcpy(g, executable, (IrInstructionMemcpy *)instruction);
- case IrInstructionIdSlice:
- return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);
+ case IrInstructionIdSliceGen:
+ return ir_render_slice(g, executable, (IrInstructionSliceGen *)instruction);
case IrInstructionIdBreakpoint:
return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);
case IrInstructionIdReturnAddress:
@@ -5697,6 +5704,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction);
case IrInstructionIdResizeSlice:
return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
+ case IrInstructionIdPtrOfArrayToSlice:
+ return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction);
}
zig_unreachable();
}
@@ -6831,9 +6840,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdSlice) {
- IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
- slot = &slice_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdOptionalWrap) {
IrInstructionOptionalWrap *maybe_wrap_instruction = (IrInstructionOptionalWrap *)instruction;
slot = &maybe_wrap_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 26d0d59b28..cc28d3981c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -700,8 +700,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemcpy *) {
return IrInstructionIdMemcpy;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) {
- return IrInstructionIdSlice;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceSrc *) {
+ return IrInstructionIdSliceSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceGen *) {
+ return IrInstructionIdSliceGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
@@ -880,6 +884,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *)
return IrInstructionIdResolveResult;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {
+ return IrInstructionIdPtrOfArrayToSlice;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
return IrInstructionIdOpaqueType;
}
@@ -2216,14 +2224,15 @@ static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)
+static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, ResultLoc *result_loc)
{
- IrInstructionSlice *instruction = ir_build_instruction(irb, scope, source_node);
+ IrInstructionSliceSrc *instruction = ir_build_instruction(irb, scope, source_node);
instruction->ptr = ptr;
instruction->start = start;
instruction->end = end;
instruction->safety_check_on = safety_check_on;
+ instruction->result_loc = result_loc;
ir_ref_instruction(ptr, irb->current_basic_block);
ir_ref_instruction(start, irb->current_basic_block);
@@ -2232,6 +2241,26 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour
return &instruction->base;
}
+static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
+ IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
+{
+ IrInstructionSliceGen *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = slice_type;
+ instruction->ptr = ptr;
+ instruction->start = start;
+ instruction->end = end;
+ instruction->safety_check_on = safety_check_on;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+ ir_ref_instruction(start, ira->new_irb.current_basic_block);
+ if (end) ir_ref_instruction(end, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) {
IrInstructionMemberCount *instruction = ir_build_instruction(irb, scope, source_node);
instruction->container = container;
@@ -2705,11 +2734,12 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
}
static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *dest_type, IrInstruction *target)
+ IrInstruction *dest_type, IrInstruction *target, ResultLoc *result_loc)
{
IrInstructionImplicitCast *instruction = ir_build_instruction(irb, scope, source_node);
instruction->dest_type = dest_type;
instruction->target = target;
+ instruction->result_loc = result_loc;
ir_ref_instruction(dest_type, irb->current_basic_block);
ir_ref_instruction(target, irb->current_basic_block);
@@ -3082,6 +3112,21 @@ static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *so
return &instruction->base;
}
+static IrInstruction *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionPtrOfArrayToSlice *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction,
IrInstruction *array, ZigType *result_type)
{
@@ -5717,7 +5762,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
return irb->codegen->invalid_instruction;
if (type_instruction != nullptr) {
- IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value);
+ IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value,
+ &result_loc_var->base);
ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base);
}
@@ -7086,7 +7132,7 @@ static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode
return ir_build_const_void(irb, parent_scope, node);
}
-static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) {
+static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
assert(node->type == NodeTypeSliceExpr);
AstNodeSliceExpr *slice_expr = &node->data.slice_expr;
@@ -7111,7 +7157,8 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
end_value = nullptr;
}
- return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
+ IrInstruction *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, true, result_loc);
+ return ir_lval_wrap(irb, scope, slice, lval, result_loc);
}
static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
@@ -7659,7 +7706,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
- IrInstruction *undef_promise_result = ir_build_implicit_cast(irb, scope, node, promise_result_type, undef);
+ IrInstruction *undef_promise_result = ir_build_implicit_cast(irb, scope, node, promise_result_type, undef, nullptr);
build_decl_var_and_init(irb, scope, node, result_var, undef_promise_result, "result", const_bool_false);
IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
@@ -8001,7 +8048,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeDefer:
return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc);
case NodeTypeSliceExpr:
- return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval, result_loc);
+ return ir_gen_slice(irb, scope, node, lval, result_loc);
case NodeTypeCatchExpr:
return ir_gen_catch(irb, scope, node, lval, result_loc);
case NodeTypeContainerDecl:
@@ -8028,15 +8075,19 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
zig_unreachable();
}
+static ResultLoc *no_result_loc(void) {
+ ResultLocNone *result_loc_none = allocate(1);
+ result_loc_none->base.id = ResultLocIdNone;
+ return &result_loc_none->base;
+}
+
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
ResultLoc *result_loc)
{
if (result_loc == nullptr) {
// Create a result location indicating there is none - but if one gets created
// it will be properly distributed.
- ResultLocNone *result_loc_none = allocate(1);
- result_loc_none->base.id = ResultLocIdNone;
- result_loc = &result_loc_none->base;
+ result_loc = no_result_loc();
}
IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);
@@ -8098,7 +8149,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
- IrInstruction *undef_coro_frame = ir_build_implicit_cast(irb, coro_scope, node, coro_frame_type_value, undef);
+ IrInstruction *undef_coro_frame = ir_build_implicit_cast(irb, coro_scope, node, coro_frame_type_value, undef, nullptr);
build_decl_var_and_init(irb, coro_scope, node, promise_var, undef_coro_frame, "promise", const_bool_false);
coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
@@ -8106,7 +8157,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
- IrInstruction *null_await_handle = ir_build_implicit_cast(irb, coro_scope, node, await_handle_type_val, null_value);
+ IrInstruction *null_await_handle = ir_build_implicit_cast(irb, coro_scope, node, await_handle_type_val, null_value, nullptr);
build_decl_var_and_init(irb, coro_scope, node, await_handle_var, null_await_handle, "await_handle", const_bool_false);
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
@@ -8169,7 +8220,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
Buf *instruction_addresses_name = buf_create_from_str("instruction_addresses");
IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name, false);
- IrInstruction *slice_value = ir_build_slice(irb, scope, node, return_addresses_ptr, zero, nullptr, false);
+ IrInstruction *slice_value = ir_build_slice_src(irb, scope, node, return_addresses_ptr, zero, nullptr, false, no_result_loc());
ir_build_store_ptr(irb, scope, node, addrs_slice_ptr, slice_value);
}
@@ -8275,7 +8326,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
- IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
+ IrInstruction *mem_slice = ir_build_slice_src(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false,
+ no_result_loc());
size_t arg_count = 5;
IrInstruction **args = allocate(arg_count);
args[0] = implicit_allocator_ptr; // self
@@ -10417,7 +10469,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
zig_unreachable();
case CastOpErrSet:
case CastOpBitCast:
- case CastOpPtrOfArrayToSlice:
zig_panic("TODO");
case CastOpNoop:
{
@@ -10574,7 +10625,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
}
static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *value, ZigType *wanted_type)
+ IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
{
Error err;
@@ -10605,11 +10656,12 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
}
}
- IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node,
- wanted_type, value, CastOpPtrOfArrayToSlice);
- result->value.type = wanted_type;
- ir_add_alloca(ira, result, wanted_type);
- return result;
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, value, result_loc_inst);
}
static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
@@ -11195,7 +11247,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
}
static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *array_arg, ZigType *wanted_type)
+ IrInstruction *array_arg, ZigType *wanted_type, ResultLoc *result_loc)
{
assert(is_slice(wanted_type));
// In this function we honor the const-ness of wanted_type, because
@@ -11227,12 +11279,14 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
- IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,
- source_instr->source_node, array_ptr, start, end, false);
- result->value.type = wanted_type;
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ IrInstruction *result = ir_build_slice_gen(ira, source_instr, wanted_type, array_ptr, start, end, false, result_loc_inst);
result->value.data.rh_slice.id = RuntimeHintSliceIdLen;
result->value.data.rh_slice.len = array_type->data.array.len;
- ir_add_alloca(ira, result, result->value.type);
return result;
}
@@ -11929,7 +11983,7 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {
}
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
- ZigType *wanted_type, IrInstruction *value)
+ ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)
{
Error err;
ZigType *actual_type = value->value.type;
@@ -12017,11 +12071,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
- IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
@@ -12103,7 +12157,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
source_node, false).id == ConstCastResultIdOk)
{
- return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);
+ return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
}
}
@@ -12120,11 +12174,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
source_node, false).id == ConstCastResultIdOk)
{
- IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
@@ -12167,7 +12221,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
array_type->data.array.child_type, source_node,
!slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
- return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type);
+ return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
}
}
@@ -12198,11 +12252,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
source_node, false).id == ConstCastResultIdOk)
{
- IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
@@ -12380,7 +12434,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ira->codegen->invalid_instruction;
}
-static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {
+static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type,
+ ResultLoc *result_loc)
+{
assert(value);
assert(value != ira->codegen->invalid_instruction);
assert(!expected_type || !type_is_invalid(expected_type));
@@ -12393,7 +12449,11 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
if (value->value.type->id == ZigTypeIdUnreachable)
return value;
- return ir_analyze_cast(ira, value, expected_type, value);
+ return ir_analyze_cast(ira, value, expected_type, value, result_loc);
+}
+
+static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {
+ return ir_implicit_cast_with_result(ira, value, expected_type, nullptr);
}
static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
@@ -14744,7 +14804,7 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns
if (type_is_invalid(target->value.type))
return ira->codegen->invalid_instruction;
- return ir_implicit_cast(ira, target, dest_type);
+ return ir_implicit_cast_with_result(ira, target, dest_type, instruction->result_loc);
}
static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
@@ -15687,7 +15747,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
IrInstruction *arg = call_instruction->args[0]->child;
- IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg);
+ IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg,
+ call_instruction->result_loc);
if (type_is_invalid(cast_instruction->value.type))
return ira->codegen->invalid_instruction;
return ir_finish_anal(ira, cast_instruction);
@@ -21165,7 +21226,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
return result;
}
-static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) {
+static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSliceSrc *instruction) {
IrInstruction *ptr_ptr = instruction->ptr->child;
if (type_is_invalid(ptr_ptr->value.type))
return ira->codegen->invalid_instruction;
@@ -21454,12 +21515,13 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
return result;
}
- IrInstruction *new_instruction = ir_build_slice(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node,
- ptr_ptr, casted_start, end, instruction->safety_check_on);
- new_instruction->value.type = return_type;
- ir_add_alloca(ira, new_instruction, return_type);
- return new_instruction;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ return_type, nullptr);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+ return ir_build_slice_gen(ira, &instruction->base, return_type,
+ ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc);
}
static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {
@@ -23900,6 +23962,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
case IrInstructionIdCmpxchgGen:
case IrInstructionIdArrayToVector:
case IrInstructionIdVectorToArray:
+ case IrInstructionIdPtrOfArrayToSlice:
case IrInstructionIdAssertZero:
case IrInstructionIdAssertNonNull:
case IrInstructionIdResizeSlice:
@@ -23908,6 +23971,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
case IrInstructionIdCallGen:
case IrInstructionIdReturnPtr:
case IrInstructionIdAllocaGen:
+ case IrInstructionIdSliceGen:
zig_unreachable();
case IrInstructionIdReturn:
@@ -24042,8 +24106,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_memset(ira, (IrInstructionMemset *)instruction);
case IrInstructionIdMemcpy:
return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);
- case IrInstructionIdSlice:
- return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);
+ case IrInstructionIdSliceSrc:
+ return ir_analyze_instruction_slice(ira, (IrInstructionSliceSrc *)instruction);
case IrInstructionIdMemberCount:
return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
case IrInstructionIdMemberType:
@@ -24321,6 +24385,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdGlobalAsm:
case IrInstructionIdUndeclaredIdent:
case IrInstructionIdEndExpr:
+ case IrInstructionIdPtrOfArrayToSlice:
+ case IrInstructionIdSliceGen:
return true;
case IrInstructionIdPhi:
@@ -24360,7 +24426,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdIntType:
case IrInstructionIdVectorType:
case IrInstructionIdBoolNot:
- case IrInstructionIdSlice:
+ case IrInstructionIdSliceSrc:
case IrInstructionIdMemberCount:
case IrInstructionIdMemberType:
case IrInstructionIdMemberName:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 925d802e6d..e80ddf401b 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -858,14 +858,26 @@ static void ir_print_memcpy(IrPrint *irp, IrInstructionMemcpy *instruction) {
fprintf(irp->f, ")");
}
-static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {
+static void ir_print_slice_src(IrPrint *irp, IrInstructionSliceSrc *instruction) {
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, "[");
ir_print_other_instruction(irp, instruction->start);
fprintf(irp->f, "..");
if (instruction->end)
ir_print_other_instruction(irp, instruction->end);
- fprintf(irp->f, "]");
+ fprintf(irp->f, "]result=");
+ ir_print_result_loc(irp, instruction->result_loc);
+}
+
+static void ir_print_slice_gen(IrPrint *irp, IrInstructionSliceGen *instruction) {
+ ir_print_other_instruction(irp, instruction->ptr);
+ fprintf(irp->f, "[");
+ ir_print_other_instruction(irp, instruction->start);
+ fprintf(irp->f, "..");
+ if (instruction->end)
+ ir_print_other_instruction(irp, instruction->end);
+ fprintf(irp->f, "]result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {
@@ -1086,6 +1098,13 @@ static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *i
fprintf(irp->f, ")");
}
+static void ir_print_ptr_of_array_to_slice(IrPrint *irp, IrInstructionPtrOfArrayToSlice *instruction) {
+ fprintf(irp->f, "PtrOfArrayToSlice(");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
+}
+
static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) {
fprintf(irp->f, "AssertZero(");
ir_print_other_instruction(irp, instruction->target);
@@ -1758,8 +1777,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdMemcpy:
ir_print_memcpy(irp, (IrInstructionMemcpy *)instruction);
break;
- case IrInstructionIdSlice:
- ir_print_slice(irp, (IrInstructionSlice *)instruction);
+ case IrInstructionIdSliceSrc:
+ ir_print_slice_src(irp, (IrInstructionSliceSrc *)instruction);
+ break;
+ case IrInstructionIdSliceGen:
+ ir_print_slice_gen(irp, (IrInstructionSliceGen *)instruction);
break;
case IrInstructionIdMemberCount:
ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
@@ -1992,6 +2014,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdVectorToArray:
ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
break;
+ case IrInstructionIdPtrOfArrayToSlice:
+ ir_print_ptr_of_array_to_slice(irp, (IrInstructionPtrOfArrayToSlice *)instruction);
+ break;
case IrInstructionIdAssertZero:
ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
break;
--
cgit v1.2.3
From eaa9d8bdac7f64e38a39607e5d5574f88f8fe875 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 16:20:13 -0400
Subject: result location semantics for optional wrap
---
src/all_types.hpp | 4 ++--
src/codegen.cpp | 13 +++++--------
src/ir.cpp | 33 +++++++++++++++++++++------------
src/ir_print.cpp | 11 ++++++-----
4 files changed, 34 insertions(+), 27 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 73580619ed..d2e7a7f631 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3095,8 +3095,8 @@ struct IrInstructionUnwrapErrPayload {
struct IrInstructionOptionalWrap {
IrInstruction base;
- IrInstruction *value;
- LLVMValueRef tmp_ptr;
+ IrInstruction *operand;
+ IrInstruction *result_loc;
};
struct IrInstructionErrWrapPayload {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index f748c575b0..e88cee4186 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4956,20 +4956,20 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
return LLVMConstInt(LLVMInt1Type(), 1, false);
}
- LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
+ LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
if (!handle_is_ptr(wanted_type)) {
return payload_val;
}
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
+ LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
// child_type and instruction->value->value.type may differ by constness
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
- LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
+ LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {
@@ -6840,9 +6840,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdOptionalWrap) {
- IrInstructionOptionalWrap *maybe_wrap_instruction = (IrInstructionOptionalWrap *)instruction;
- slot = &maybe_wrap_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdErrWrapPayload) {
IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
slot = &err_wrap_payload_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index cc28d3981c..58f6b14450 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1758,11 +1758,17 @@ static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
-static IrInstruction *ir_build_maybe_wrap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
- IrInstructionOptionalWrap *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->value = value;
+static IrInstruction *ir_build_optional_wrap(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_ty,
+ IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionOptionalWrap *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_ty;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -11035,7 +11041,7 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
}
static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
- ZigType *wanted_type)
+ ZigType *wanted_type, ResultLoc *result_loc)
{
assert(wanted_type->id == ZigTypeIdOptional);
@@ -11061,10 +11067,13 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
return &const_instruction->base;
}
- IrInstruction *result = ir_build_maybe_wrap(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
- result->value.type = wanted_type;
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ IrInstruction *result = ir_build_optional_wrap(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_maybe = RuntimeHintOptionalNonNull;
- ir_add_alloca(ira, result, wanted_type);
return result;
}
@@ -12009,12 +12018,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
false).id == ConstCastResultIdOk)
{
- return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
} else if (actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
- return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
} else {
return ira->codegen->invalid_instruction;
}
@@ -12038,7 +12047,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_child_type);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type, result_loc);
}
}
}
@@ -24387,6 +24396,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdEndExpr:
case IrInstructionIdPtrOfArrayToSlice:
case IrInstructionIdSliceGen:
+ case IrInstructionIdOptionalWrap:
return true;
case IrInstructionIdPhi:
@@ -24436,7 +24446,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdHandle:
case IrInstructionIdTestErr:
case IrInstructionIdUnwrapErrCode:
- case IrInstructionIdOptionalWrap:
case IrInstructionIdErrWrapCode:
case IrInstructionIdErrWrapPayload:
case IrInstructionIdFnProto:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index e80ddf401b..6cad5c1dea 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -970,10 +970,11 @@ static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayl
}
}
-static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
- fprintf(irp->f, "@maybeWrap(");
- ir_print_other_instruction(irp, instruction->value);
- fprintf(irp->f, ")");
+static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
+ fprintf(irp->f, "@optionalWrap(");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {
@@ -1820,7 +1821,7 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);
break;
case IrInstructionIdOptionalWrap:
- ir_print_maybe_wrap(irp, (IrInstructionOptionalWrap *)instruction);
+ ir_print_optional_wrap(irp, (IrInstructionOptionalWrap *)instruction);
break;
case IrInstructionIdErrWrapCode:
ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);
--
cgit v1.2.3
From 4f085b8d2c8ffb03dd15b789ad5867904faae13d Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 16:55:07 -0400
Subject: result location semantics for error union wrapping a payload
---
BRANCH_TODO | 14 +-------------
src/all_types.hpp | 4 ++--
src/codegen.cpp | 16 +++++++---------
src/ir.cpp | 43 ++++++++++++++++++++++++++++++-------------
src/ir_print.cpp | 5 +++--
5 files changed, 43 insertions(+), 39 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index e744162fa0..f6fd78dbaa 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -6,17 +6,5 @@ look at all the ir_gen_node ir_gen_node_extra calls and make sure result locatio
migrate all the alloca_list to alloca_gen_list
-inferred comptime
-
-
- if (lval == LValNone) {
- if (result_loc->id == ResultLocIdNone)
- return value;
- }
-
- assert(lval == LValPtr);
-
- // We needed a pointer to a value, but we got a value. So we create
- // an instruction which just makes a pointer of it.
- return ir_build_ref(irb, scope, value->source_node, value, false, false);
+comptime expressions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index d2e7a7f631..f13f16152d 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3102,8 +3102,8 @@ struct IrInstructionOptionalWrap {
struct IrInstructionErrWrapPayload {
IrInstruction base;
- IrInstruction *value;
- LLVMValueRef tmp_ptr;
+ IrInstruction *operand;
+ IrInstruction *result_loc;
};
struct IrInstructionErrWrapCode {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index e88cee4186..69b234d160 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5002,7 +5002,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
if (!type_has_bits(err_set_type)) {
- return ir_llvm_value(g, instruction->value);
+ return ir_llvm_value(g, instruction->operand);
}
LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
@@ -5010,17 +5010,18 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
if (!type_has_bits(payload_type))
return ok_err_val;
- assert(instruction->tmp_ptr);
- LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
+ LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
+
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
- LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
+ LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
@@ -6840,9 +6841,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdErrWrapPayload) {
- IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
- slot = &err_wrap_payload_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdErrWrapCode) {
IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
slot = &err_wrap_code_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 58f6b14450..10752cdc64 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1773,11 +1773,17 @@ static IrInstruction *ir_build_optional_wrap(IrAnalyze *ira, IrInstruction *sour
return &instruction->base;
}
-static IrInstruction *ir_build_err_wrap_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
- IrInstructionErrWrapPayload *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->value = value;
+static IrInstruction *ir_build_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionErrWrapPayload *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -11078,12 +11084,13 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
}
static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *value, ZigType *wanted_type)
+ IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
{
assert(wanted_type->id == ZigTypeIdErrorUnion);
+ ZigType *payload_type = wanted_type->data.error_union.payload_type;
+ ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
if (instr_is_comptime(value)) {
- ZigType *payload_type = wanted_type->data.error_union.payload_type;
IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type);
if (type_is_invalid(casted_payload->value.type))
return ira->codegen->invalid_instruction;
@@ -11093,7 +11100,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
return ira->codegen->invalid_instruction;
ConstExprValue *err_set_val = create_const_vals(1);
- err_set_val->type = wanted_type->data.error_union.err_set_type;
+ err_set_val->type = err_set_type;
err_set_val->special = ConstValSpecialStatic;
err_set_val->data.x_err_set = nullptr;
@@ -11106,10 +11113,19 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
return &const_instruction->base;
}
- IrInstruction *result = ir_build_err_wrap_payload(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
- result->value.type = wanted_type;
+ IrInstruction *result_loc_inst;
+ if (handle_is_ptr(wanted_type)) {
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ } else {
+ result_loc_inst = nullptr;
+ }
+
+ IrInstruction *result = ir_build_err_wrap_payload(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_error_union = RuntimeHintErrorUnionNonError;
- ir_add_alloca(ira, result, wanted_type);
return result;
}
@@ -12057,12 +12073,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
source_node, false).id == ConstCastResultIdOk)
{
- return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
+ return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
} else if (actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
- return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
+ return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
} else {
return ira->codegen->invalid_instruction;
}
@@ -24447,7 +24463,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTestErr:
case IrInstructionIdUnwrapErrCode:
case IrInstructionIdErrWrapCode:
- case IrInstructionIdErrWrapPayload:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
@@ -24512,6 +24527,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
(IrInstructionUnwrapErrPayload *)instruction;
return unwrap_err_payload_instruction->safety_check_on;
}
+ case IrInstructionIdErrWrapPayload:
+ return reinterpret_cast(instruction)->result_loc != nullptr;
}
zig_unreachable();
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 6cad5c1dea..7cff6f3d70 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -985,8 +985,9 @@ static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instr
static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {
fprintf(irp->f, "@errWrapPayload(");
- ir_print_other_instruction(irp, instruction->value);
- fprintf(irp->f, ")");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {
--
cgit v1.2.3
From b9c033ae1ac9c21a5729407b9a6ede88854654aa Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 17:28:25 -0400
Subject: result location semantics for error union wrapping an error
---
src/all_types.hpp | 4 +--
src/codegen.cpp | 18 ++++++--------
src/ir.cpp | 73 +++++++++++++++++++++++++++++++++++++------------------
src/ir_print.cpp | 5 ++--
4 files changed, 61 insertions(+), 39 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index f13f16152d..7c06719e90 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3109,8 +3109,8 @@ struct IrInstructionErrWrapPayload {
struct IrInstructionErrWrapCode {
IrInstruction base;
- IrInstruction *value;
- LLVMValueRef tmp_ptr;
+ IrInstruction *operand;
+ IrInstruction *result_loc;
};
struct IrInstructionFnProto {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 69b234d160..ce844806d9 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4977,20 +4977,19 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable
assert(wanted_type->id == ZigTypeIdErrorUnion);
- ZigType *payload_type = wanted_type->data.error_union.payload_type;
- ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
+ LLVMValueRef err_val = ir_llvm_value(g, instruction->operand);
- LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
-
- if (!type_has_bits(payload_type) || !type_has_bits(err_set_type))
+ if (!handle_is_ptr(wanted_type))
return err_val;
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
gen_store_untyped(g, err_val, err_tag_ptr, 0, false);
- return instruction->tmp_ptr;
+ // TODO store undef to the payload
+
+ return result_loc;
}
static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {
@@ -6841,9 +6840,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdErrWrapCode) {
- IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
- slot = &err_wrap_code_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdCmpxchgGen) {
IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
slot = &cmpxchg_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 10752cdc64..1a0c7d3144 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1788,11 +1788,17 @@ static IrInstruction *ir_build_err_wrap_payload(IrAnalyze *ira, IrInstruction *s
return &instruction->base;
}
-static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
- IrInstructionErrWrapCode *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->value = value;
+static IrInstruction *ir_build_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionErrWrapCode *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -11172,7 +11178,9 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
return result;
}
-static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
+static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *wanted_type, ResultLoc *result_loc)
+{
assert(wanted_type->id == ZigTypeIdErrorUnion);
IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type);
@@ -11196,10 +11204,20 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
return &const_instruction->base;
}
- IrInstruction *result = ir_build_err_wrap_code(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
- result->value.type = wanted_type;
+ IrInstruction *result_loc_inst;
+ if (handle_is_ptr(wanted_type)) {
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ } else {
+ result_loc_inst = nullptr;
+ }
+
+
+ IrInstruction *result = ir_build_err_wrap_code(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_error_union = RuntimeHintErrorUnionError;
- ir_add_alloca(ira, result, wanted_type);
return result;
}
@@ -12293,7 +12311,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (wanted_type->id == ZigTypeIdErrorUnion &&
actual_type->id == ZigTypeIdErrorSet)
{
- return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
+ return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type, result_loc);
}
// cast from typed number to integer or float literal.
@@ -15615,12 +15633,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
}
FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
- IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
- impl_fn_type_id->return_type, nullptr);
- if (result_loc != nullptr &&
- (type_is_invalid(result_loc->value.type) || result_loc->value.type->id == ZigTypeIdUnreachable))
- {
- return result_loc;
+ IrInstruction *result_loc;
+ if (handle_is_ptr(impl_fn_type_id->return_type)) {
+ result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
+ impl_fn_type_id->return_type, nullptr);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+ call_instruction->result_loc->written = true;
+ } else {
+ result_loc = nullptr;
}
if (fn_type_can_fail(impl_fn_type_id)) {
@@ -15634,7 +15656,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
return ir_finish_anal(ira, result);
}
- call_instruction->result_loc->written = handle_is_ptr(impl_fn_type_id->return_type);
assert(async_allocator_inst == nullptr);
IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
impl_fn, nullptr, impl_param_count, casted_args, fn_inline,
@@ -15733,15 +15754,18 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
return ira->codegen->invalid_instruction;
}
- IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
- return_type, nullptr);
- if (result_loc != nullptr &&
- (type_is_invalid(result_loc->value.type) || result_loc->value.type->id == ZigTypeIdUnreachable))
- {
- return result_loc;
+ IrInstruction *result_loc;
+ if (handle_is_ptr(return_type)) {
+ result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
+ return_type, nullptr);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+ call_instruction->result_loc->written = true;
+ } else {
+ result_loc = nullptr;
}
- call_instruction->result_loc->written = handle_is_ptr(return_type);
IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
call_param_count, casted_args, fn_inline, false, nullptr, casted_new_stack,
result_loc, return_type);
@@ -24462,7 +24486,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdHandle:
case IrInstructionIdTestErr:
case IrInstructionIdUnwrapErrCode:
- case IrInstructionIdErrWrapCode:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
@@ -24529,6 +24552,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
}
case IrInstructionIdErrWrapPayload:
return reinterpret_cast(instruction)->result_loc != nullptr;
+ case IrInstructionIdErrWrapCode:
+ return reinterpret_cast(instruction)->result_loc != nullptr;
}
zig_unreachable();
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 7cff6f3d70..30ca2aa73e 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -979,8 +979,9 @@ static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *inst
static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {
fprintf(irp->f, "@errWrapCode(");
- ir_print_other_instruction(irp, instruction->value);
- fprintf(irp->f, ")");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {
--
cgit v1.2.3
From ee3f7e20f64d715ff22eeff0b7b355bca1981ea1 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 17:49:36 -0400
Subject: result location semantics for cmpxchg
---
src/all_types.hpp | 12 ++++++------
src/codegen.cpp | 19 ++++++++-----------
src/ir.cpp | 33 +++++++++++++++++++++++----------
src/ir_print.cpp | 6 ++++--
4 files changed, 41 insertions(+), 29 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 7c06719e90..7a4a450c49 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2862,26 +2862,26 @@ struct IrInstructionEmbedFile {
struct IrInstructionCmpxchgSrc {
IrInstruction base;
+ bool is_weak;
IrInstruction *type_value;
IrInstruction *ptr;
IrInstruction *cmp_value;
IrInstruction *new_value;
IrInstruction *success_order_value;
IrInstruction *failure_order_value;
-
- bool is_weak;
+ ResultLoc *result_loc;
};
struct IrInstructionCmpxchgGen {
IrInstruction base;
+ bool is_weak;
+ AtomicOrder success_order;
+ AtomicOrder failure_order;
IrInstruction *ptr;
IrInstruction *cmp_value;
IrInstruction *new_value;
- LLVMValueRef tmp_ptr;
- AtomicOrder success_order;
- AtomicOrder failure_order;
- bool is_weak;
+ IrInstruction *result_loc;
};
struct IrInstructionFence {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index ce844806d9..7845ee7289 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4516,28 +4516,28 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
success_order, failure_order, instruction->is_weak);
- ZigType *maybe_type = instruction->base.value.type;
- assert(maybe_type->id == ZigTypeIdOptional);
- ZigType *child_type = maybe_type->data.maybe.child_type;
+ ZigType *optional_type = instruction->base.value.type;
+ assert(optional_type->id == ZigTypeIdOptional);
+ ZigType *child_type = optional_type->data.maybe.child_type;
- if (!handle_is_ptr(maybe_type)) {
+ if (!handle_is_ptr(optional_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
}
- assert(instruction->tmp_ptr != nullptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
assert(type_has_bits(child_type));
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
- LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
+ LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
- LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
+ LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) {
@@ -6840,9 +6840,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdCmpxchgGen) {
- IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
- slot = &cmpxchg_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdResizeSlice) {
IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction;
slot = &resize_slice_instruction->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 1a0c7d3144..6a2ad9125c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -2032,8 +2032,7 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
- IrInstruction *success_order_value, IrInstruction *failure_order_value,
- bool is_weak)
+ IrInstruction *success_order_value, IrInstruction *failure_order_value, bool is_weak, ResultLoc *result_loc)
{
IrInstructionCmpxchgSrc *instruction = ir_build_instruction(irb, scope, source_node);
instruction->type_value = type_value;
@@ -2043,6 +2042,7 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
instruction->success_order_value = success_order_value;
instruction->failure_order_value = failure_order_value;
instruction->is_weak = is_weak;
+ instruction->result_loc = result_loc;
ir_ref_instruction(type_value, irb->current_basic_block);
ir_ref_instruction(ptr, irb->current_basic_block);
@@ -2054,22 +2054,25 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
- AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
+ AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstruction *result_loc)
{
IrInstructionCmpxchgGen *instruction = ir_build_instruction(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
instruction->ptr = ptr;
instruction->cmp_value = cmp_value;
instruction->new_value = new_value;
instruction->success_order = success_order;
instruction->failure_order = failure_order;
instruction->is_weak = is_weak;
+ instruction->result_loc = result_loc;
ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -4420,7 +4423,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg5_value;
IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
- arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
+ arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
+ result_loc);
return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc);
}
case BuiltinFnIdFence:
@@ -20439,6 +20443,18 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
if (type_is_invalid(ptr->value.type))
return ira->codegen->invalid_instruction;
+ ZigType *result_type = get_optional_type(ira->codegen, operand_type);
+ IrInstruction *result_loc;
+ if (handle_is_ptr(result_type)) {
+ result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ result_type, nullptr);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+ } else {
+ result_loc = nullptr;
+ }
+
// TODO let this be volatile
ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false);
IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr, ptr_type);
@@ -20502,12 +20518,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
zig_panic("TODO compile-time execution of cmpxchg");
}
- IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
+ return ir_build_cmpxchg_gen(ira, &instruction->base, result_type,
casted_ptr, casted_cmp_value, casted_new_value,
- success_order, failure_order, instruction->is_weak);
- result->value.type = get_optional_type(ira->codegen, operand_type);
- ir_add_alloca(ira, result, result->value.type);
- return result;
+ success_order, failure_order, instruction->is_weak, result_loc);
}
static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 30ca2aa73e..1dd84254fc 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -730,7 +730,8 @@ static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruct
ir_print_other_instruction(irp, instruction->success_order_value);
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, instruction->failure_order_value);
- fprintf(irp->f, ")");
+ fprintf(irp->f, ")result=");
+ ir_print_result_loc(irp, instruction->result_loc);
}
static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
@@ -740,7 +741,8 @@ static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruct
ir_print_other_instruction(irp, instruction->cmp_value);
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, instruction->new_value);
- fprintf(irp->f, ", TODO print atomic orders)");
+ fprintf(irp->f, ", TODO print atomic orders)result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
--
cgit v1.2.3
From 65f6ea66f4a86c45004547bb5ac079b8286f980e Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 18:34:27 -0400
Subject: result loc semantics for `@sliceToBytes` and `@bytesToSlice`
---
src/all_types.hpp | 4 +++-
src/codegen.cpp | 13 ++++---------
src/ir.cpp | 42 ++++++++++++++++++++++++++++++------------
src/ir_print.cpp | 3 ++-
4 files changed, 39 insertions(+), 23 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 7a4a450c49..e196b6f38f 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2635,7 +2635,7 @@ struct IrInstructionResizeSlice {
IrInstruction base;
IrInstruction *operand;
- LLVMValueRef tmp_ptr;
+ IrInstruction *result_loc;
};
struct IrInstructionContainerInitList {
@@ -2925,6 +2925,7 @@ struct IrInstructionToBytes {
IrInstruction base;
IrInstruction *target;
+ ResultLoc *result_loc;
};
struct IrInstructionFromBytes {
@@ -2932,6 +2933,7 @@ struct IrInstructionFromBytes {
IrInstruction *dest_child_type;
IrInstruction *target;
+ ResultLoc *result_loc;
};
struct IrInstructionIntToFloat {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 7845ee7289..d84bcd1327 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2943,7 +2943,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
assert(expr_val);
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
assert(wanted_type->id == ZigTypeIdStruct);
assert(wanted_type->data.structure.is_slice);
assert(actual_type->id == ZigTypeIdStruct);
@@ -2964,7 +2964,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), "");
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
+ LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc,
(unsigned)wanted_ptr_index, "");
gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
@@ -2997,12 +2997,10 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
- LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)wanted_len_index, "");
+ LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_len_index, "");
gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
-
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
@@ -6840,9 +6838,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdResizeSlice) {
- IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction;
- slot = &resize_slice_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdLoadPtrGen) {
IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction;
slot = &load_ptr_inst->tmp_ptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 6a2ad9125c..31235acb85 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1574,14 +1574,16 @@ static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *sourc
}
static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction,
- IrInstruction *operand, ZigType *ty)
+ IrInstruction *operand, ZigType *ty, IrInstruction *result_loc)
{
IrInstructionResizeSlice *instruction = ir_build_instruction(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = ty;
instruction->operand = operand;
+ instruction->result_loc = result_loc;
ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -2131,19 +2133,25 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}
-static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
+static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target,
+ ResultLoc *result_loc)
+{
IrInstructionToBytes *instruction = ir_build_instruction(irb, scope, source_node);
instruction->target = target;
+ instruction->result_loc = result_loc;
ir_ref_instruction(target, irb->current_basic_block);
return &instruction->base;
}
-static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_child_type, IrInstruction *target) {
+static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *dest_child_type, IrInstruction *target, ResultLoc *result_loc)
+{
IrInstructionFromBytes *instruction = ir_build_instruction(irb, scope, source_node);
instruction->dest_child_type = dest_child_type;
instruction->target = target;
+ instruction->result_loc = result_loc;
ir_ref_instruction(dest_child_type, irb->current_basic_block);
ir_ref_instruction(target, irb->current_basic_block);
@@ -4599,7 +4607,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);
+ IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc);
return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdToBytes:
@@ -4609,7 +4617,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
- IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);
+ IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc);
return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
case BuiltinFnIdIntToFloat:
@@ -5681,7 +5689,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
ir_ref_instruction(elem_ptr, irb->current_basic_block);
ResultLoc *child_result_loc = &result_loc_inst->base;
- IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, child_result_loc);
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, &result_loc->scope_elide->base,
+ LValNone, child_result_loc);
if (expr_value == irb->codegen->invalid_instruction)
return expr_value;
@@ -14687,6 +14696,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
if (fn_entry != nullptr) {
fn_entry->alloca_gen_list.append(alloca_gen);
}
+ result_loc->written = true;
result_loc->resolved_loc = &alloca_gen->base;
return result_loc->resolved_loc;
}
@@ -20766,6 +20776,12 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
}
}
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ dest_slice_type, nullptr);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+
if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {
known_len = casted_value->value.data.rh_slice.len;
have_known_len = true;
@@ -20785,9 +20801,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
}
}
- IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type);
- ir_add_alloca(ira, result, dest_slice_type);
- return result;
+ return ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type, result_loc);
}
static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
@@ -20839,9 +20853,13 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
return result;
}
- IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type);
- ir_add_alloca(ira, result, dest_slice_type);
- return result;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ dest_slice_type, nullptr);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+
+ return ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type, result_loc);
}
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 1dd84254fc..3729fab308 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1125,7 +1125,8 @@ static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *i
static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {
fprintf(irp->f, "@resizeSlice(");
ir_print_other_instruction(irp, instruction->operand);
- fprintf(irp->f, ")");
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_alloca_src(IrPrint *irp, IrInstructionAllocaSrc *instruction) {
--
cgit v1.2.3
From 9a324ecb42f69791d49bc8e62e935aec75b5e920 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 19:11:34 -0400
Subject: result loc semantics for loading packed struct pointer to packed
struct
```zig
export fn entry() void {
var x = foo();
var ptr = &x.b;
var y = ptr.*;
}
const Foo = packed struct {
a: u24 = 1,
b: Bar = Bar{},
};
const Bar = packed struct {
a: u4 = 2,
b: u4 = 3,
};
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%x = alloca %Foo, align 1
%ptr = alloca i32*, align 8
%y = alloca %Bar, align 1
call fastcc void @foo(%Foo* sret %x), !dbg !55
call void @llvm.dbg.declare(metadata %Foo* %x, metadata !39, metadata !DIExpression()), !dbg !56
%0 = getelementptr inbounds %Foo, %Foo* %x, i32 0, i32 0, !dbg !57
store i32* %0, i32** %ptr, align 8, !dbg !57
call void @llvm.dbg.declare(metadata i32** %ptr, metadata !51, metadata !DIExpression()), !dbg !58
%1 = load i32*, i32** %ptr, align 8, !dbg !59
%2 = load i32, i32* %1, align 1, !dbg !60
%3 = lshr i32 %2, 24, !dbg !60
%4 = trunc i32 %3 to i8, !dbg !60
%5 = bitcast %Bar* %y to i8*, !dbg !60
store i8 %4, i8* %5, !dbg !60
call void @llvm.dbg.declare(metadata %Bar* %y, metadata !54, metadata !DIExpression()), !dbg !61
ret void, !dbg !62
}
```
---
src/all_types.hpp | 5 +-
src/codegen.cpp | 9 ++--
src/ir.cpp | 145 ++++++++++++++++++++++++++++++------------------------
src/ir_print.cpp | 4 +-
4 files changed, 90 insertions(+), 73 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index e196b6f38f..d7e11f7102 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2449,8 +2449,9 @@ struct IrInstructionUnOp {
IrInstruction base;
IrUnOp op_id;
- IrInstruction *value;
LVal lval;
+ IrInstruction *value;
+ ResultLoc *result_loc;
};
enum IrBinOp {
@@ -2507,7 +2508,7 @@ struct IrInstructionLoadPtrGen {
IrInstruction base;
IrInstruction *ptr;
- LLVMValueRef tmp_ptr;
+ IrInstruction *result_loc;
};
struct IrInstructionStorePtr {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d84bcd1327..994194c5eb 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3376,13 +3376,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
if (handle_is_ptr(child_type)) {
- assert(instruction->tmp_ptr != nullptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
- LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,
LLVMPointerType(same_size_int, 0), "");
LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
- return instruction->tmp_ptr;
+ return result_loc;
}
if (child_type->id == ZigTypeIdFloat) {
@@ -6838,9 +6838,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } else if (instruction->id == IrInstructionIdLoadPtrGen) {
- IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction;
- slot = &load_ptr_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 31235acb85..305b534791 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -161,7 +161,8 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
ResultLoc *result_loc);
static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);
-static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
+static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
+ ResultLoc *result_loc);
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing);
@@ -1467,12 +1468,13 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
}
static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
- IrInstruction *value, LVal lval)
+ IrInstruction *value, LVal lval, ResultLoc *result_loc)
{
IrInstructionUnOp *instruction = ir_build_instruction(irb, scope, source_node);
instruction->op_id = op_id;
instruction->value = value;
instruction->lval = lval;
+ instruction->result_loc = result_loc;
ir_ref_instruction(value, irb->current_basic_block);
@@ -1482,7 +1484,7 @@ static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode
static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
IrInstruction *value)
{
- return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone);
+ return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr);
}
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
@@ -2471,14 +2473,16 @@ static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *sourc
}
static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction,
- IrInstruction *ptr, ZigType *ty)
+ IrInstruction *ptr, ZigType *ty, IrInstruction *result_loc)
{
IrInstructionLoadPtrGen *instruction = ir_build_instruction(
&ira->new_irb, source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = ty;
instruction->ptr = ptr;
+ instruction->result_loc = result_loc;
ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -8028,7 +8032,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
// We essentially just converted any lvalue from &(x.*) to (&x).*;
// this inhibits checking that x is a pointer later, so we directly
// record whether the pointer check is needed
- return ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval);
+ IrInstruction *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc);
+ return ir_expr_wrap(irb, scope, un_op, result_loc);
}
case NodeTypeUnwrapOptional: {
AstNode *expr_node = node->data.unwrap_optional.expr;
@@ -11312,7 +11317,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
IrInstruction *array_ptr = nullptr;
IrInstruction *array;
if (array_arg->value.type->id == ZigTypeIdPointer) {
- array = ir_get_deref(ira, source_instr, array_arg);
+ array = ir_get_deref(ira, source_instr, array_arg, nullptr);
array_ptr = array_arg;
} else {
array = array_arg;
@@ -12512,60 +12517,71 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
return ir_implicit_cast_with_result(ira, value, expected_type, nullptr);
}
-static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
+static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
+ ResultLoc *result_loc)
+{
Error err;
ZigType *type_entry = ptr->value.type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id == ZigTypeIdPointer) {
- ZigType *child_type = type_entry->data.pointer.child_type;
- // if the child type has one possible value, the deref is comptime
- switch (type_has_one_possible_value(ira->codegen, child_type)) {
- case OnePossibleValueInvalid:
- return ira->codegen->invalid_instruction;
- case OnePossibleValueYes:
- return ir_const(ira, source_instruction, child_type);
- case OnePossibleValueNo:
- break;
+
+ if (type_entry->id != ZigTypeIdPointer) {
+ ir_add_error_node(ira, source_instruction->source_node,
+ buf_sprintf("attempt to dereference non-pointer type '%s'",
+ buf_ptr(&type_entry->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ ZigType *child_type = type_entry->data.pointer.child_type;
+ // if the child type has one possible value, the deref is comptime
+ switch (type_has_one_possible_value(ira->codegen, child_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ return ir_const(ira, source_instruction, child_type);
+ case OnePossibleValueNo:
+ break;
+ }
+ if (instr_is_comptime(ptr)) {
+ if (ptr->value.special == ConstValSpecialUndef) {
+ ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
+ return ira->codegen->invalid_instruction;
}
- if (instr_is_comptime(ptr)) {
- if (ptr->value.special == ConstValSpecialUndef) {
- ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
- return ira->codegen->invalid_instruction;
- }
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
- ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
- {
- ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
- if (pointee->special != ConstValSpecialRuntime) {
- IrInstruction *result = ir_const(ira, source_instruction, child_type);
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
+ ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
+ {
+ ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
+ if (pointee->special != ConstValSpecialRuntime) {
+ IrInstruction *result = ir_const(ira, source_instruction, child_type);
- if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
- &ptr->value)))
- {
- return ira->codegen->invalid_instruction;
- }
- result->value.type = child_type;
- return result;
+ if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
+ &ptr->value)))
+ {
+ return ira->codegen->invalid_instruction;
}
+ result->value.type = child_type;
+ return result;
}
}
- // if the instruction is a const ref instruction we can skip it
- if (ptr->id == IrInstructionIdRef) {
- IrInstructionRef *ref_inst = reinterpret_cast(ptr);
- return ref_inst->value;
- }
- IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type);
- if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
- ir_add_alloca(ira, result, child_type);
+ }
+ // if the instruction is a const ref instruction we can skip it
+ if (ptr->id == IrInstructionIdRef) {
+ IrInstructionRef *ref_inst = reinterpret_cast(ptr);
+ return ref_inst->value;
+ }
+
+ IrInstruction *result_loc_inst;
+ if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
+ if (result_loc == nullptr) result_loc = no_result_loc();
+ result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
}
- return result;
} else {
- ir_add_error_node(ira, source_instruction->source_node,
- buf_sprintf("attempt to dereference non-pointer type '%s'",
- buf_ptr(&type_entry->name)));
- return ira->codegen->invalid_instruction;
+ result_loc_inst = nullptr;
}
+
+ return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst);
}
static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
@@ -14585,7 +14601,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
ZigVar *coro_allocator_var = ira->old_irb.exec->coro_allocator_var;
assert(coro_allocator_var != nullptr);
IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var);
- IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst);
+ IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst, nullptr);
assert(result->value.type != nullptr);
return result;
}
@@ -15313,7 +15329,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
first_arg = first_arg_ptr;
} else {
- first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
+ first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
if (type_is_invalid(first_arg->value.type))
return ira->codegen->invalid_instruction;
}
@@ -15472,7 +15488,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
first_arg = first_arg_ptr;
} else {
- first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
+ first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
if (type_is_invalid(first_arg->value.type))
return ira->codegen->invalid_instruction;
}
@@ -15516,7 +15532,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
if (type_is_invalid(arg_var_ptr_inst->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst);
+ IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst, nullptr);
if (type_is_invalid(arg_tuple_arg->value.type))
return ira->codegen->invalid_instruction;
@@ -15702,7 +15718,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
{
first_arg = first_arg_ptr;
} else {
- first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
+ first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
if (type_is_invalid(first_arg->value.type))
return ira->codegen->invalid_instruction;
}
@@ -16113,7 +16129,7 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr, instruction->result_loc);
if (result == ira->codegen->invalid_instruction)
return ira->codegen->invalid_instruction;
@@ -16994,7 +17010,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
assert(container_ptr->value.type->id == ZigTypeIdPointer);
if (container_type->id == ZigTypeIdPointer) {
ZigType *bare_type = container_ref_type(container_type);
- IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);
+ IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr, nullptr);
IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type, field_ptr_instruction->initializing);
return result;
} else {
@@ -17339,7 +17355,7 @@ static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruct
IrInstruction *ptr = instruction->ptr->child;
if (type_is_invalid(ptr->value.type))
return ira->codegen->invalid_instruction;
- return ir_get_deref(ira, &instruction->base, ptr);
+ return ir_get_deref(ira, &instruction->base, ptr, nullptr);
}
static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
@@ -17807,7 +17823,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
}
if (!safety_check_on)
return base_ptr;
- IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr);
+ IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr, nullptr);
ir_build_assert_non_null(ira, source_instr, c_ptr_val);
return base_ptr;
}
@@ -18162,7 +18178,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
+ IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
result->value.type = target_type;
return result;
}
@@ -18192,7 +18208,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
+ IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
union_value->value.type = target_type;
IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
@@ -18216,7 +18232,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
+ IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
enum_value->value.type = target_type;
return enum_value;
}
@@ -23105,7 +23121,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
if (lval == LValPtr) {
return var_ptr;
} else {
- return ir_get_deref(ira, &instruction->base, var_ptr);
+ return ir_get_deref(ira, &instruction->base, var_ptr, nullptr);
}
}
case TldIdFn: {
@@ -23640,7 +23656,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
}
if (instr_is_comptime(casted_ptr)) {
- IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr, nullptr);
ir_assert(result->value.type != nullptr, &instruction->base);
return result;
}
@@ -24474,7 +24490,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdUnOp:
case IrInstructionIdBinOp:
case IrInstructionIdLoadPtr:
- case IrInstructionIdLoadPtrGen:
case IrInstructionIdConst:
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
@@ -24585,6 +24600,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
return reinterpret_cast(instruction)->result_loc != nullptr;
case IrInstructionIdErrWrapCode:
return reinterpret_cast(instruction)->result_loc != nullptr;
+ case IrInstructionIdLoadPtrGen:
+ return reinterpret_cast(instruction)->result_loc != nullptr;
}
zig_unreachable();
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 3729fab308..4bec292997 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -397,8 +397,10 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
}
static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) {
+ fprintf(irp->f, "loadptr(");
ir_print_other_instruction(irp, instruction->ptr);
- fprintf(irp->f, ".*");
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
--
cgit v1.2.3
From 4582ec518f9984a26c68b8427a914bad6dc80c4a Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 19:49:24 -0400
Subject: result location semantics for vector to array
```zig
export fn entry() void {
var x: @Vector(4, i32) = undefined;
var y: [4]i32 = x;
}
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%x = alloca <4 x i32>, align 16
%y = alloca [4 x i32], align 4
%0 = bitcast <4 x i32>* %x to i8*, !dbg !47
call void @llvm.memset.p0i8.i64(i8* align 16 %0, i8 -86, i64 16, i1 false), !dbg !47
call void @llvm.dbg.declare(metadata <4 x i32>* %x, metadata !39, metadata !DIExpression()), !dbg !47
%1 = load <4 x i32>, <4 x i32>* %x, align 16, !dbg !48
%2 = bitcast [4 x i32]* %y to <4 x i32>*, !dbg !48
store <4 x i32> %1, <4 x i32>* %2, align 16, !dbg !48
call void @llvm.dbg.declare(metadata [4 x i32]* %y, metadata !45, metadata !DIExpression()), !dbg !49
ret void, !dbg !50
}
```
---
src/all_types.hpp | 2 +-
src/codegen.cpp | 10 +++-------
src/ir.cpp | 18 +++++++++++-------
src/ir_print.cpp | 3 ++-
4 files changed, 17 insertions(+), 16 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index d7e11f7102..6e04fada04 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3522,7 +3522,7 @@ struct IrInstructionVectorToArray {
IrInstruction base;
IrInstruction *vector;
- LLVMValueRef tmp_ptr;
+ IrInstruction *result_loc;
};
struct IrInstructionAssertZero {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 994194c5eb..53800d4eec 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5386,12 +5386,12 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
ZigType *array_type = instruction->base.value.type;
assert(array_type->id == ZigTypeIdArray);
assert(handle_is_ptr(array_type));
- assert(instruction->tmp_ptr);
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
- LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
+ LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
gen_store_untyped(g, vector, casted_ptr, 0, false);
- return instruction->tmp_ptr;
+ return result_loc;
}
static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
@@ -6838,10 +6838,6 @@ static void do_code_gen(CodeGen *g) {
slot = &ref_instruction->tmp_ptr;
assert(instruction->value.type->id == ZigTypeIdPointer);
slot_type = instruction->value.type->data.pointer.child_type;
- } 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);
- slot = &vector_to_array_instruction->tmp_ptr;
} else {
zig_unreachable();
}
diff --git a/src/ir.cpp b/src/ir.cpp
index 305b534791..8282b8de2a 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -3131,16 +3131,16 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
}
static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
- IrInstruction *vector, ZigType *result_type)
+ ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc)
{
IrInstructionVectorToArray *instruction = ir_build_instruction(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = result_type;
instruction->vector = vector;
+ instruction->result_loc = result_loc;
ir_ref_instruction(vector, ira->new_irb.current_basic_block);
-
- ir_add_alloca(ira, &instruction->base, result_type);
+ ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -11985,7 +11985,7 @@ static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *
}
static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *vector, ZigType *array_type)
+ IrInstruction *vector, ZigType *array_type, ResultLoc *result_loc)
{
if (instr_is_comptime(vector)) {
// arrays and vectors have the same ConstExprValue representation
@@ -11994,7 +11994,11 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
result->value.type = array_type;
return result;
}
- return ir_build_vector_to_array(ira, source_instr, vector, array_type);
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
+ return ir_build_vector_to_array(ira, source_instr, array_type, vector, result_loc_inst);
}
static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
@@ -12453,7 +12457,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, wanted_type->data.array.child_type,
actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
{
- return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);
+ return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type, result_loc);
}
// cast from [N]T to @Vector(N, T)
@@ -24484,6 +24488,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPtrOfArrayToSlice:
case IrInstructionIdSliceGen:
case IrInstructionIdOptionalWrap:
+ case IrInstructionIdVectorToArray:
return true;
case IrInstructionIdPhi:
@@ -24578,7 +24583,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFromBytes:
case IrInstructionIdToBytes:
case IrInstructionIdEnumToInt:
- case IrInstructionIdVectorToArray:
case IrInstructionIdArrayToVector:
case IrInstructionIdHasDecl:
case IrInstructionIdAllocaSrc:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 4bec292997..90fd5aa069 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1102,7 +1102,8 @@ static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *i
static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
fprintf(irp->f, "VectorToArray(");
ir_print_other_instruction(irp, instruction->vector);
- fprintf(irp->f, ")");
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
}
static void ir_print_ptr_of_array_to_slice(IrPrint *irp, IrInstructionPtrOfArrayToSlice *instruction) {
--
cgit v1.2.3
From f6d4e2565e7c0eea7e50e50dd808246d65d9f200 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 23:51:43 -0400
Subject: use result loc for ref instruction
---
src/all_types.hpp | 9 ++++++++-
src/codegen.cpp | 22 +++++++++-------------
src/ir.cpp | 44 ++++++++++++++++++++++++++++++++------------
src/ir_print.cpp | 10 ++++++++++
4 files changed, 59 insertions(+), 26 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index a758f5d906..bd72a4fccf 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2234,6 +2234,7 @@ enum IrInstructionId {
IrInstructionIdCDefine,
IrInstructionIdCUndef,
IrInstructionIdRef,
+ IrInstructionIdRefGen,
IrInstructionIdCompileErr,
IrInstructionIdCompileLog,
IrInstructionIdErrName,
@@ -2812,11 +2813,17 @@ struct IrInstructionRef {
IrInstruction base;
IrInstruction *value;
- LLVMValueRef tmp_ptr;
bool is_const;
bool is_volatile;
};
+struct IrInstructionRefGen {
+ IrInstruction base;
+
+ IrInstruction *operand;
+ IrInstruction *result_loc;
+};
+
struct IrInstructionCompileErr {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 53800d4eec..5e3938a4ae 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4212,17 +4212,17 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru
return phi;
}
-static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRef *instruction) {
+static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRefGen *instruction) {
if (!type_has_bits(instruction->base.value.type)) {
return nullptr;
}
- LLVMValueRef value = ir_llvm_value(g, instruction->value);
- if (handle_is_ptr(instruction->value->value.type)) {
+ LLVMValueRef value = ir_llvm_value(g, instruction->operand);
+ if (handle_is_ptr(instruction->operand->value.type)) {
return value;
} else {
- assert(instruction->tmp_ptr);
- gen_store_untyped(g, value, instruction->tmp_ptr, 0, false);
- return instruction->tmp_ptr;
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+ gen_store_untyped(g, value, result_loc, 0, false);
+ return result_loc;
}
}
@@ -5530,6 +5530,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdResolveResult:
case IrInstructionIdContainerInitList:
case IrInstructionIdSliceSrc:
+ case IrInstructionIdRef:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5584,8 +5585,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
case IrInstructionIdPhi:
return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
- case IrInstructionIdRef:
- return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
+ case IrInstructionIdRefGen:
+ return ir_render_ref(g, executable, (IrInstructionRefGen *)instruction);
case IrInstructionIdErrName:
return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
case IrInstructionIdCmpxchgGen:
@@ -6833,11 +6834,6 @@ static void do_code_gen(CodeGen *g) {
if (instruction->id == IrInstructionIdCast) {
IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
slot = &cast_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdRef) {
- IrInstructionRef *ref_instruction = (IrInstructionRef *)instruction;
- slot = &ref_instruction->tmp_ptr;
- assert(instruction->value.type->id == ZigTypeIdPointer);
- slot_type = instruction->value.type->data.pointer.child_type;
} else {
zig_unreachable();
}
diff --git a/src/ir.cpp b/src/ir.cpp
index 16638de6b3..d132f5110f 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -617,6 +617,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
return IrInstructionIdRef;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionRefGen *) {
+ return IrInstructionIdRefGen;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {
return IrInstructionIdCompileErr;
}
@@ -1961,6 +1965,21 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source
return &instruction->base;
}
+static IrInstruction *ir_build_ref_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
+ IrInstruction *operand, IrInstruction *result_loc)
+{
+ IrInstructionRefGen *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->operand = operand;
+ instruction->result_loc = result_loc;
+
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) {
IrInstructionCompileErr *instruction = ir_build_instruction(irb, scope, source_node);
instruction->msg = msg;
@@ -2636,11 +2655,8 @@ static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
-static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node,
- Tld *tld, LVal lval)
-{
- IrInstructionDeclRef *instruction = ir_build_instruction(
- irb, scope, source_node);
+static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) {
+ IrInstructionDeclRef *instruction = ir_build_instruction(irb, scope, source_node);
instruction->tld = tld;
instruction->lval = lval;
@@ -11335,15 +11351,16 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
- IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
- source_instruction->source_node, value, is_const, is_volatile);
- new_instruction->value.type = ptr_type;
- new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
+
+ IrInstruction *result_loc;
if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
- ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- assert(fn_entry);
- fn_entry->alloca_list.append(new_instruction);
+ result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr);
+ } else {
+ result_loc = nullptr;
}
+
+ IrInstruction *new_instruction = ir_build_ref_gen(ira, source_instruction, ptr_type, value, result_loc);
+ new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
return new_instruction;
}
@@ -24119,6 +24136,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
case IrInstructionIdReturnPtr:
case IrInstructionIdAllocaGen:
case IrInstructionIdSliceGen:
+ case IrInstructionIdRefGen:
zig_unreachable();
case IrInstructionIdReturn:
@@ -24653,6 +24671,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
return reinterpret_cast(instruction)->result_loc != nullptr;
case IrInstructionIdLoadPtrGen:
return reinterpret_cast(instruction)->result_loc != nullptr;
+ case IrInstructionIdRefGen:
+ return reinterpret_cast(instruction)->result_loc != nullptr;
}
zig_unreachable();
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 90fd5aa069..1935c0d7f6 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -668,6 +668,13 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
ir_print_other_instruction(irp, instruction->value);
}
+static void ir_print_ref_gen(IrPrint *irp, IrInstructionRefGen *instruction) {
+ fprintf(irp->f, "@ref(");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, instruction->result_loc);
+}
+
static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) {
fprintf(irp->f, "@compileError(");
ir_print_other_instruction(irp, instruction->msg);
@@ -1711,6 +1718,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdRef:
ir_print_ref(irp, (IrInstructionRef *)instruction);
break;
+ case IrInstructionIdRefGen:
+ ir_print_ref_gen(irp, (IrInstructionRefGen *)instruction);
+ break;
case IrInstructionIdCompileErr:
ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
break;
--
cgit v1.2.3
From d504318f2e0f3054c772abbd34f938f2cefa6ccc Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 10 Jun 2019 23:54:28 -0400
Subject: remove the final legacy stack allocation
---
BRANCH_TODO | 3 ---
src/all_types.hpp | 2 --
src/codegen.cpp | 14 --------------
src/ir.cpp | 25 ++++++-------------------
4 files changed, 6 insertions(+), 38 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index f6fd78dbaa..f730eb64f5 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -4,7 +4,4 @@ Scratch pad for stuff to do before merging master
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
return ir_gen_comptime(irb, scope, node, lval);
-migrate all the alloca_list to alloca_gen_list
-
comptime expressions
-
diff --git a/src/all_types.hpp b/src/all_types.hpp
index bd72a4fccf..1d935fee2b 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1369,7 +1369,6 @@ struct ZigFn {
AstNode *fn_no_inline_set_node;
AstNode *fn_static_eval_set_node;
- ZigList alloca_list;
ZigList alloca_gen_list;
ZigList variable_list;
@@ -2635,7 +2634,6 @@ struct IrInstructionCast {
IrInstruction *value;
ZigType *dest_type;
CastOp cast_op;
- LLVMValueRef tmp_ptr;
};
struct IrInstructionResizeSlice {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 5e3938a4ae..a75ef29169 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -6826,20 +6826,6 @@ static void do_code_gen(CodeGen *g) {
get_ptr_align(g, ptr_type));
}
- for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {
- IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
- LLVMValueRef *slot;
- ZigType *slot_type = instruction->value.type;
- uint32_t alignment_bytes = 0;
- if (instruction->id == IrInstructionIdCast) {
- IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
- slot = &cast_instruction->tmp_ptr;
- } else {
- zig_unreachable();
- }
- *slot = build_alloca(g, slot_type, "", alignment_bytes);
- }
-
ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base);
unsigned gen_i_init = want_first_arg_sret(g, fn_type_id) ? 1 : 0;
diff --git a/src/ir.cpp b/src/ir.cpp
index d132f5110f..07df62fd02 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -181,7 +181,6 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
-static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
ZigType *ptr_type);
static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
@@ -10497,15 +10496,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
}
}
-static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry) {
- if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {
- ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
- if (fn_entry != nullptr) {
- fn_entry->alloca_list.append(instruction);
- }
- }
-}
-
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
ConstGlobalRefs *global_refs = dest->global_refs;
assert(!same_global_refs || src->global_refs != nullptr);
@@ -10631,7 +10621,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
}
static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
- ZigType *wanted_type, CastOp cast_op, bool need_alloca)
+ ZigType *wanted_type, CastOp cast_op)
{
if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {
IrInstruction *result = ir_const(ira, source_instr, wanted_type);
@@ -10644,9 +10634,6 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
} else {
IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op);
result->value.type = wanted_type;
- if (need_alloca) {
- ir_add_alloca(ira, result, wanted_type);
- }
return result;
}
}
@@ -12121,7 +12108,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (const_cast_result.id == ConstCastResultIdInvalid)
return ira->codegen->invalid_instruction;
if (const_cast_result.id == ConstCastResultIdOk) {
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
+ return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
}
// cast from T to ?T
@@ -20752,7 +20739,7 @@ static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstru
} else {
op = CastOpNumLitToConcrete;
}
- return ir_resolve_cast(ira, &instruction->base, target, dest_type, op, false);
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, op);
} else {
return ira->codegen->invalid_instruction;
}
@@ -20975,7 +20962,7 @@ static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInst
return ira->codegen->invalid_instruction;
}
- return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat);
}
static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {
@@ -20997,7 +20984,7 @@ static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInst
return ira->codegen->invalid_instruction;
}
- return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false);
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt);
}
static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
@@ -21049,7 +21036,7 @@ static IrInstruction *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstr
}
ZigType *u1_type = get_int_type(ira->codegen, false, 1);
- return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);
+ return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt);
}
static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
--
cgit v1.2.3
From 7411a88d5f8109ced238cf14205ae36575f02f21 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 11 Jun 2019 00:27:10 -0400
Subject: fix comptime function calls
---
BRANCH_TODO | 4 ++--
src/analyze.cpp | 28 ++++++++++++++++++++++++++++
src/analyze.hpp | 1 +
src/codegen.cpp | 28 ----------------------------
src/ir.cpp | 2 ++
5 files changed, 33 insertions(+), 30 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index f730eb64f5..854b2c0ee7 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,7 +1,7 @@
Scratch pad for stuff to do before merging master
=================================================
+uncomment all the behavior tests
+
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
return ir_gen_comptime(irb, scope, node, lval);
-
-comptime expressions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 0168dad6ea..beaa9f1486 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -7293,3 +7293,31 @@ void src_assert(bool ok, AstNode *source_node) {
const char *msg = "assertion failed. This is a bug in the Zig compiler.";
stage2_panic(msg, strlen(msg));
}
+
+bool scope_is_elided(Scope *scope) {
+ for (;;) {
+ switch (scope->id) {
+ case ScopeIdElide:
+ if (reinterpret_cast(scope)->activated)
+ return true;
+ // fallthrough
+ case ScopeIdBlock:
+ case ScopeIdDefer:
+ case ScopeIdDeferExpr:
+ case ScopeIdVarDecl:
+ case ScopeIdLoop:
+ case ScopeIdSuspend:
+ case ScopeIdCoroPrelude:
+ case ScopeIdRuntime:
+ scope = scope->parent;
+ continue;
+ case ScopeIdFnDef:
+ case ScopeIdCompTime:
+ case ScopeIdDecls:
+ case ScopeIdCImport:
+ return false;
+ }
+ zig_unreachable();
+ }
+}
+
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 2f3ec663da..2c5250d7e9 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -253,5 +253,6 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa
void src_assert(bool ok, AstNode *source_node);
bool is_container(ZigType *type_entry);
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
+bool scope_is_elided(Scope *scope);
#endif
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a75ef29169..7ee299aab7 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5709,34 +5709,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
-static bool scope_is_elided(Scope *scope) {
- for (;;) {
- switch (scope->id) {
- case ScopeIdDecls:
- case ScopeIdCompTime:
- case ScopeIdCImport:
- zig_unreachable();
- case ScopeIdElide:
- if (reinterpret_cast(scope)->activated)
- return true;
- // fallthrough
- case ScopeIdBlock:
- case ScopeIdDefer:
- case ScopeIdDeferExpr:
- case ScopeIdVarDecl:
- case ScopeIdLoop:
- case ScopeIdSuspend:
- case ScopeIdCoroPrelude:
- case ScopeIdRuntime:
- scope = scope->parent;
- continue;
- case ScopeIdFnDef:
- return false;
- }
- zig_unreachable();
- }
-}
-
static void ir_render(CodeGen *g, ZigFn *fn_entry) {
assert(fn_entry);
diff --git a/src/ir.cpp b/src/ir.cpp
index 07df62fd02..1ea509745e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -8503,6 +8503,8 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
IrBasicBlock *bb = exec->basic_block_list.at(0);
for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
IrInstruction *instruction = bb->instruction_list.at(i);
+ if (scope_is_elided(instruction->scope))
+ continue;
if (instruction->id == IrInstructionIdReturn) {
IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;
IrInstruction *value = ret_inst->value;
--
cgit v1.2.3
From 06f307ff77adac0451b10643a033714c1d309010 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 11 Jun 2019 12:19:57 -0400
Subject: fix implicit casting return value struct/arary init to optional
---
BRANCH_TODO | 3 +++
src/all_types.hpp | 3 ++-
src/codegen.cpp | 37 ++++++++++++++++++++++---------------
src/ir.cpp | 49 +++++++++++++++++++++++++++++++++++--------------
src/ir_print.cpp | 5 +++--
5 files changed, 65 insertions(+), 32 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 854b2c0ee7..fba18ed35b 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,6 +1,9 @@
Scratch pad for stuff to do before merging master
=================================================
+struct & array init when the result is casted to anyerror!T
+struct & array init when the result is casted to anyerror!?T
+
uncomment all the behavior tests
look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 1d935fee2b..35f8745fd6 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2770,8 +2770,9 @@ struct IrInstructionTestNonNull {
struct IrInstructionOptionalUnwrapPtr {
IrInstruction base;
- IrInstruction *base_ptr;
bool safety_check_on;
+ bool initializing;
+ IrInstruction *base_ptr;
};
struct IrInstructionCtz {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 7ee299aab7..2d1ea07bf3 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -838,9 +838,7 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
{
LLVMValueRef instruction = LLVMBuildStore(g->builder, value, ptr);
if (is_volatile) LLVMSetVolatile(instruction, true);
- if (alignment == 0) {
- LLVMSetAlignment(instruction, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(value)));
- } else {
+ if (alignment != 0) {
LLVMSetAlignment(instruction, alignment);
}
return instruction;
@@ -2384,16 +2382,19 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
+ if (return_instruction->value == nullptr) {
+ LLVMBuildRetVoid(g->builder);
+ return nullptr;
+ }
+
ZigType *return_type = return_instruction->value->value.type;
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
assert(g->cur_ret_ptr);
- if (return_instruction->value->value.special != ConstValSpecialRuntime) {
- // if it's comptime we have to do this but if it's runtime trust that
- // result location mechanism took care of it.
- LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
- gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
- }
+ src_assert(return_instruction->value->value.special != ConstValSpecialRuntime,
+ return_instruction->base.source_node);
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
+ gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
LLVMBuildRetVoid(g->builder);
} else if (handle_is_ptr(return_type)) {
LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
@@ -4068,9 +4069,9 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
ZigType *maybe_type = ptr_type->data.pointer.child_type;
assert(maybe_type->id == ZigTypeIdOptional);
ZigType *child_type = maybe_type->data.maybe.child_type;
- LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
- if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
- LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
+ LLVMValueRef base_ptr = ir_llvm_value(g, instruction->base_ptr);
+ if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
+ LLVMValueRef maybe_handle = get_handle_value(g, base_ptr, maybe_type, ptr_type);
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
@@ -4086,10 +4087,16 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
} else {
bool is_scalar = !handle_is_ptr(maybe_type);
if (is_scalar) {
- return maybe_ptr;
+ return base_ptr;
} else {
- LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
- return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, "");
+ LLVMValueRef optional_struct_ref = get_handle_value(g, base_ptr, maybe_type, ptr_type);
+ if (instruction->initializing) {
+ LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP(g->builder, optional_struct_ref,
+ maybe_null_index, "");
+ LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
+ gen_store_untyped(g, non_null_bit, non_null_bit_ptr, 0, false);
+ }
+ return LLVMBuildStructGEP(g->builder, optional_struct_ref, maybe_child_index, "");
}
}
}
diff --git a/src/ir.cpp b/src/ir.cpp
index b05fe835b7..31c40ac168 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -187,6 +187,8 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
ZigType *dest_type);
static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
ResultLoc *result_loc, ZigType *value_type, IrInstruction *value);
+static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -1095,13 +1097,15 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
return &cond_br_instruction->base;
}
-static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *return_value) {
+static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *return_value)
+{
IrInstructionReturn *return_instruction = ir_build_instruction(irb, scope, source_node);
return_instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
return_instruction->base.value.special = ConstValSpecialStatic;
return_instruction->value = return_value;
- ir_ref_instruction(return_value, irb->current_basic_block);
+ if (return_value != nullptr) ir_ref_instruction(return_value, irb->current_basic_block);
return &return_instruction->base;
}
@@ -1756,11 +1760,12 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
}
static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *base_ptr, bool safety_check_on)
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing)
{
IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node);
instruction->base_ptr = base_ptr;
instruction->safety_check_on = safety_check_on;
+ instruction->initializing = initializing;
ir_ref_instruction(base_ptr, irb->current_basic_block);
@@ -3918,7 +3923,7 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, ok_block);
- IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false);
IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers[1].base);
IrBasicBlock *after_ok_block = irb->current_basic_block;
@@ -6009,7 +6014,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block, result_loc);
ir_set_cursor_at_end_and_append_block(irb, body_block);
- IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
+ IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false);
IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
ir_build_ref(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);
@@ -6609,7 +6614,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
var_symbol, is_const, is_const, is_shadowable, is_comptime);
- IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
+ IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false);
IrInstruction *var_ptr = var_is_ptr ? ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
var_scope = var->child_scope;
@@ -8094,7 +8099,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
if (maybe_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
+ IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false);
if (lval == LValPtr)
return unwrapped_ptr;
@@ -8375,7 +8380,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// a register or local variable which does not get spilled into the frame,
// otherwise llvm tries to access memory inside the destroyed frame.
IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
- irb->exec->await_handle_var_ptr, false);
+ irb->exec->await_handle_var_ptr, false, false);
IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
ir_build_br(irb, scope, node, check_free_block, const_bool_false);
@@ -12871,6 +12876,14 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
if (type_is_invalid(value->value.type))
return ir_unreach_error(ira);
+ if (!instr_is_comptime(value) && handle_is_ptr(ira->explicit_return_type)) {
+ // result location mechanism took care of it.
+ IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
+ }
+
IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
if (type_is_invalid(casted_value->value.type)) {
AstNode *source_node = ira->explicit_return_type_source_node;
@@ -14925,10 +14938,17 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns
}
static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
- ZigType *ty = ir_resolve_type(ira, instruction->ty->child);
- if (type_is_invalid(ty))
+ ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
+ if (type_is_invalid(implicit_elem_type))
return ira->codegen->invalid_instruction;
- return ir_resolve_result(ira, &instruction->base, instruction->result_loc, ty, nullptr);
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ implicit_elem_type, nullptr);
+ ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
+ ZigType *actual_elem_type = result_loc->value.type->data.pointer.child_type;
+ if (actual_elem_type->id == ZigTypeIdOptional && implicit_elem_type->id != ZigTypeIdOptional) {
+ return ir_analyze_unwrap_optional_payload(ira, &instruction->base, result_loc, false, true);
+ }
+ return result_loc;
}
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
@@ -17876,7 +17896,7 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
}
static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *base_ptr, bool safety_check_on)
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing)
{
ZigType *ptr_type = base_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
@@ -17948,7 +17968,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
}
IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
- source_instr->source_node, base_ptr, safety_check_on);
+ source_instr->source_node, base_ptr, safety_check_on, initializing);
result->value.type = result_type;
return result;
}
@@ -17960,7 +17980,8 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
- return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
+ return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr,
+ instruction->safety_check_on, false);
}
static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) {
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 1935c0d7f6..64e6f07ade 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -61,9 +61,10 @@ static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
}
static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
- assert(return_instruction->value);
fprintf(irp->f, "return ");
- ir_print_other_instruction(irp, return_instruction->value);
+ if (return_instruction->value != nullptr) {
+ ir_print_other_instruction(irp, return_instruction->value);
+ }
}
static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
--
cgit v1.2.3
From fc8d8812404e79716e15fd301058032485e8bb64 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 11 Jun 2019 13:27:01 -0400
Subject: fix struct and array init when result casted to anyerror!?T
---
BRANCH_TODO | 1 -
src/all_types.hpp | 10 +++++-----
src/codegen.cpp | 7 ++++++-
src/ir.cpp | 54 +++++++++++++++++++++++++++++++++---------------------
4 files changed, 44 insertions(+), 28 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index fba18ed35b..881a2f7d26 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,7 +1,6 @@
Scratch pad for stuff to do before merging master
=================================================
-struct & array init when the result is casted to anyerror!T
struct & array init when the result is casted to anyerror!?T
uncomment all the behavior tests
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 35f8745fd6..598394cb45 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2343,10 +2343,6 @@ enum IrInstructionId {
};
struct IrInstruction {
- IrInstructionId id;
- // true if this instruction was generated by zig and not from user code
- bool is_gen;
-
Scope *scope;
AstNode *source_node;
ConstExprValue value;
@@ -2360,6 +2356,9 @@ struct IrInstruction {
// with this child field.
IrInstruction *child;
IrBasicBlock *owner_bb;
+ IrInstructionId id;
+ // true if this instruction was generated by zig and not from user code
+ bool is_gen;
};
struct IrInstructionDeclVarSrc {
@@ -3102,8 +3101,9 @@ struct IrInstructionUnwrapErrCode {
struct IrInstructionUnwrapErrPayload {
IrInstruction base;
- IrInstruction *value;
bool safety_check_on;
+ bool initializing;
+ IrInstruction *value;
};
struct IrInstructionOptionalWrap {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2d1ea07bf3..a040d377cf 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4908,7 +4908,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
IrInstructionUnwrapErrPayload *instruction)
{
- bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
+ bool want_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base) &&
g->errors_by_index.length > 1;
if (!want_safety && !type_has_bits(instruction->base.value.type))
return nullptr;
@@ -4944,6 +4944,11 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
}
if (type_has_bits(payload_type)) {
+ if (instruction->initializing) {
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
+ LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
+ gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
+ }
return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");
} else {
return nullptr;
diff --git a/src/ir.cpp b/src/ir.cpp
index 31c40ac168..b841f8032f 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -189,6 +189,8 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
ResultLoc *result_loc, ZigType *value_type, IrInstruction *value);
static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *base_ptr, bool safety_check_on, bool initializing);
+static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -2424,11 +2426,12 @@ static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, Ast
}
static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value, bool safety_check_on)
+ IrInstruction *value, bool safety_check_on, bool initializing)
{
IrInstructionUnwrapErrPayload *instruction = ir_build_instruction(irb, scope, source_node);
instruction->value = value;
instruction->safety_check_on = safety_check_on;
+ instruction->initializing = initializing;
ir_ref_instruction(value, irb->current_basic_block);
@@ -3572,7 +3575,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
}
ir_set_cursor_at_end_and_append_block(irb, continue_block);
- IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false, false);
if (lval == LValPtr)
return unwrapped_ptr;
else
@@ -5578,7 +5581,7 @@ static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, Ast
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true);
+ IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true, false);
if (payload_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -5915,7 +5918,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, body_block);
if (var_symbol) {
IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
- err_val_ptr, false);
+ err_val_ptr, false, false);
IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
ir_build_ref(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);
@@ -6694,7 +6697,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime);
- IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
+ IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false, false);
IrInstruction *var_ptr = var_is_ptr ?
ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
@@ -7316,7 +7319,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
ir_mark_gen(ir_build_br(irb, err_scope, node, end_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, ok_block);
- IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false);
IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers[1].base);
IrBasicBlock *after_ok_block = irb->current_basic_block;
@@ -14947,6 +14950,8 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
ZigType *actual_elem_type = result_loc->value.type->data.pointer.child_type;
if (actual_elem_type->id == ZigTypeIdOptional && implicit_elem_type->id != ZigTypeIdOptional) {
return ir_analyze_unwrap_optional_payload(ira, &instruction->base, result_loc, false, true);
+ } else if (actual_elem_type->id == ZigTypeIdErrorUnion && implicit_elem_type->id != ZigTypeIdErrorUnion) {
+ return ir_analyze_unwrap_error_payload(ira, &instruction->base, result_loc, false, true);
}
return result_loc;
}
@@ -22136,14 +22141,10 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI
return result;
}
-static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
- IrInstructionUnwrapErrPayload *instruction)
+static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on, bool initializing)
{
- assert(instruction->value->child);
- IrInstruction *value = instruction->value->child;
- if (type_is_invalid(value->value.type))
- return ira->codegen->invalid_instruction;
- ZigType *ptr_type = value->value.type;
+ ZigType *ptr_type = base_ptr->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
assert(ptr_type->id == ZigTypeIdPointer);
@@ -22153,7 +22154,7 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
return ira->codegen->invalid_instruction;
if (type_entry->id != ZigTypeIdErrorUnion) {
- ir_add_error(ira, value,
+ ir_add_error(ira, base_ptr,
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
@@ -22165,23 +22166,23 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
PtrLenSingle, 0, 0, 0, false);
- if (instr_is_comptime(value)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
+ if (instr_is_comptime(base_ptr)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
if (!ptr_val)
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
- ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+ ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
if (err_union_val == nullptr)
return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
if (err != nullptr) {
- ir_add_error(ira, &instruction->base,
+ ir_add_error(ira, source_instr,
buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ IrInstruction *result = ir_const(ira, source_instr, result_type);
result->value.data.x_ptr.special = ConstPtrSpecialRef;
result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
return result;
@@ -22189,12 +22190,23 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
}
}
- IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
+ IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, base_ptr, safety_check_on, initializing);
result->value.type = result_type;
return result;
}
+static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
+ IrInstructionUnwrapErrPayload *instruction)
+{
+ assert(instruction->value->child);
+ IrInstruction *value = instruction->value->child;
+ if (type_is_invalid(value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_analyze_unwrap_error_payload(ira, &instruction->base, value, instruction->safety_check_on, false);
+}
+
static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
AstNode *proto_node = instruction->base.source_node;
assert(proto_node->type == NodeTypeFnProto);
--
cgit v1.2.3
From e1d14e73b5f9c7a8d1a92ccd36cb689d625faf57 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 11 Jun 2019 15:44:06 -0400
Subject: fix `@bitCast` semantics when there is no parent result loc
---
src/all_types.hpp | 9 +++++++++
src/codegen.cpp | 1 +
src/ir.cpp | 41 +++++++++++++++++++++++++++++++++++++++--
src/ir_print.cpp | 10 ++++++++++
4 files changed, 59 insertions(+), 2 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 598394cb45..7a6123b145 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -44,6 +44,7 @@ struct IrAnalyze;
struct ResultLoc;
struct ResultLocPeer;
struct ResultLocPeerParent;
+struct ResultLocBitCast;
enum X64CABIClass {
X64CABIClass_Unknown,
@@ -2272,6 +2273,7 @@ enum IrInstructionId {
IrInstructionIdTestComptime,
IrInstructionIdPtrCastSrc,
IrInstructionIdPtrCastGen,
+ IrInstructionIdBitCastSrc,
IrInstructionIdBitCastGen,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
@@ -3159,6 +3161,13 @@ struct IrInstructionPtrCastGen {
bool safety_check_on;
};
+struct IrInstructionBitCastSrc {
+ IrInstruction base;
+
+ IrInstruction *operand;
+ ResultLocBitCast *result_loc_bit_cast;
+};
+
struct IrInstructionBitCastGen {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a040d377cf..beee678888 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5543,6 +5543,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdContainerInitList:
case IrInstructionIdSliceSrc:
case IrInstructionIdRef:
+ case IrInstructionIdBitCastSrc:
zig_unreachable();
case IrInstructionIdDeclVarGen:
diff --git a/src/ir.cpp b/src/ir.cpp
index d1289bb89d..df7a593601 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -792,6 +792,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
return IrInstructionIdPtrCastGen;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastSrc *) {
+ return IrInstructionIdBitCastSrc;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
return IrInstructionIdBitCastGen;
}
@@ -2515,6 +2519,18 @@ static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *sourc
return &instruction->base;
}
+static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast)
+{
+ IrInstructionBitCastSrc *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->operand = operand;
+ instruction->result_loc_bit_cast = result_loc_bit_cast;
+
+ ir_ref_instruction(operand, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_bit_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
IrInstruction *operand, ZigType *ty)
{
@@ -4941,7 +4957,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- return ir_lval_wrap(irb, scope, arg1_value, lval, result_loc);
+ IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast);
+ return ir_lval_wrap(irb, scope, bitcast, lval, result_loc);
}
case BuiltinFnIdIntToPtr:
{
@@ -14910,9 +14927,15 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
return ira->codegen->invalid_instruction;
}
+ IrInstruction *bitcasted_value;
+ if (value != nullptr) {
+ bitcasted_value = ir_analyze_bit_cast(ira, result_loc->source_instruction, value, dest_type);
+ } else {
+ bitcasted_value = nullptr;
+ }
IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
- dest_type, nullptr);
+ dest_type, bitcasted_value);
if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
parent_result_loc->value.type->id == ZigTypeIdUnreachable)
{
@@ -24168,6 +24191,17 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
return ir_const_void(ira, &instruction->base);
}
+static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) {
+ IrInstruction *operand = instruction->operand->child;
+ if (type_is_invalid(operand->value.type) || instr_is_comptime(operand) ||
+ instruction->result_loc_bit_cast->parent->gen_instruction == nullptr)
+ {
+ return operand;
+ }
+
+ return instruction->result_loc_bit_cast->parent->gen_instruction;
+}
+
static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -24472,6 +24506,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return nullptr;
case IrInstructionIdEndExpr:
return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);
+ case IrInstructionIdBitCastSrc:
+ return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
}
zig_unreachable();
}
@@ -24663,6 +24699,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
case IrInstructionIdPtrCastGen:
+ case IrInstructionIdBitCastSrc:
case IrInstructionIdBitCastGen:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 64e6f07ade..4b8b175be0 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1046,6 +1046,13 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
fprintf(irp->f, ")");
}
+static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) {
+ fprintf(irp->f, "@bitCast(");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")result=");
+ ir_print_result_loc(irp, &instruction->result_loc_bit_cast->base);
+}
+
static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {
fprintf(irp->f, "@bitCast(");
ir_print_other_instruction(irp, instruction->operand);
@@ -1860,6 +1867,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdPtrCastGen:
ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
break;
+ case IrInstructionIdBitCastSrc:
+ ir_print_bit_cast_src(irp, (IrInstructionBitCastSrc *)instruction);
+ break;
case IrInstructionIdBitCastGen:
ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
break;
--
cgit v1.2.3
From b3a4ec1bd209c022445b6f70385b3f88517e72f9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 11 Jun 2019 16:04:04 -0400
Subject: fix returning scalar values
```zig
export fn entry1() i32 {
return bar();
}
```
```llvm
define i32 @entry1() #2 !dbg !35 {
Entry:
%0 = call fastcc i32 @bar(), !dbg !39
ret i32 %0, !dbg !41
}
```
---
src/codegen.cpp | 3 ++-
src/ir.cpp | 6 +++++-
2 files changed, 7 insertions(+), 2 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index beee678888..a035c6b332 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3564,7 +3564,8 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionReturnPtr *instruction)
{
- assert(g->cur_ret_ptr != nullptr || !type_has_bits(instruction->base.value.type));
+ src_assert(g->cur_ret_ptr != nullptr || !type_has_bits(instruction->base.value.type),
+ instruction->base.source_node);
return g->cur_ret_ptr;
}
diff --git a/src/ir.cpp b/src/ir.cpp
index df7a593601..b3d5109e93 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -14866,7 +14866,11 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
}
case ResultLocIdReturn: {
bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
- if (is_comptime) return nullptr;
+ if (is_comptime)
+ return nullptr;
+ if (!type_has_bits(ira->explicit_return_type) || !handle_is_ptr(ira->explicit_return_type))
+ return nullptr;
+
ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false);
result_loc->written = true;
result_loc->resolved_loc = ir_build_return_ptr(ira, result_loc->source_instruction, ptr_return_type);
--
cgit v1.2.3
From 4ea7685a5bf2abc504571939984b9eda7441ef5d Mon Sep 17 00:00:00 2001
From: emekoi
Date: Tue, 11 Jun 2019 16:05:56 -0500
Subject: made root package available to all other packages
---
src/codegen.cpp | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 12b07ea6bc..cb767bcea7 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8505,10 +8505,8 @@ static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *ba
return add_source_file(g, package, resolved_path, import_code, SourceKindPkgMain);
}
-static ZigPackage *create_bootstrap_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
- ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");
- package->package_table.put(buf_create_from_str("@root"), pkg_with_main);
- return package;
+static ZigPackage *create_bootstrap_pkg(CodeGen *g) {
+ return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");
}
static ZigPackage *create_test_runner_pkg(CodeGen *g) {
@@ -8632,12 +8630,12 @@ static void gen_root_source(CodeGen *g) {
!g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
{
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
+ g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
}
if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup &&
g->out_type == OutTypeLib && g->is_dynamic)
{
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
+ g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap_lib.zig");
}
if (!g->error_during_imports) {
@@ -8645,7 +8643,7 @@ static void gen_root_source(CodeGen *g) {
}
if (g->is_test_build) {
create_test_compile_var_and_add_test_runner(g);
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->test_runner_package), "bootstrap.zig");
+ g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
if (!g->error_during_imports) {
semantic_analyze(g);
@@ -9629,6 +9627,13 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
if (g->std_package != nullptr) {
assert(g->compile_var_package != nullptr);
pkg->package_table.put(buf_create_from_str("std"), g->std_package);
+
+ if (g->is_test_build) {
+ pkg->package_table.put(buf_create_from_str("@root"), g->test_runner_package);
+ } else {
+ pkg->package_table.put(buf_create_from_str("@root"), g->root_package);
+ }
+
pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
}
return pkg;
--
cgit v1.2.3
From e12c7d88b28200bc64a538cd4812bfe58a6b6b78 Mon Sep 17 00:00:00 2001
From: emekoi
Date: Tue, 11 Jun 2019 16:06:24 -0500
Subject: made root package available to itself
---
src/codegen.cpp | 2 ++
1 file changed, 2 insertions(+)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index cb767bcea7..a50a416e40 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -180,6 +180,8 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
g->root_package = new_package(".", "", "");
}
+ g->root_package->package_table.put(buf_create_from_str("@root"), g->root_package);
+
g->zig_std_special_dir = buf_alloc();
os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
--
cgit v1.2.3
From 3ed6acd2d20de0a2a08ddf6549fb06a66687d96a Mon Sep 17 00:00:00 2001
From: emekoi
Date: Tue, 11 Jun 2019 18:40:55 -0500
Subject: fixed infinite loop when caching packages
---
src/codegen.cpp | 2 ++
1 file changed, 2 insertions(+)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a50a416e40..56bc9827c5 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -9373,6 +9373,8 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
// TODO: I think we need a more sophisticated detection of
// packages we have already seen
if (entry->value != pkg) {
+ auto root = pkg->package_table.maybe_get(buf_create_from_str("@root"));
+ if (root != nullptr && entry->value == root->value) continue;
cache_buf(ch, entry->key);
add_cache_pkg(g, ch, entry->value);
}
--
cgit v1.2.3
From 2ba29a1907264d6466f187cd89552a63160d3922 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 14 Jun 2019 11:01:38 -0400
Subject: fix peer result location with error code and payload
---
src/all_types.hpp | 1 +
src/codegen.cpp | 1 +
src/ir.cpp | 67 ++++++++++++++++++++++++++++++++++++------------
test/stage1/behavior.zig | 14 +++++-----
4 files changed, 59 insertions(+), 24 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index d81fec19e9..4609d246b6 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3099,6 +3099,7 @@ struct IrInstructionTestErr {
struct IrInstructionUnwrapErrCode {
IrInstruction base;
+ bool initializing;
IrInstruction *err_union_ptr;
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a035c6b332..def2f6f8eb 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4901,6 +4901,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
if (!type_has_bits(payload_type)) {
return err_union_ptr;
} else {
+ // TODO assign undef to the payload
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
}
diff --git a/src/ir.cpp b/src/ir.cpp
index a292f9a79b..5dfd84ff15 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -193,6 +193,8 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
IrInstruction *base_ptr, bool safety_check_on, bool initializing);
static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *base_ptr, bool safety_check_on, bool initializing);
+static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool initializing);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -15016,13 +15018,17 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
} else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
- IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
- result_loc, false, true);
- ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
- if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
- return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
+ if (value_type->id == ZigTypeIdErrorSet) {
+ return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
} else {
- return unwrapped_err_ptr;
+ IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
+ result_loc, false, true);
+ ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
+ if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
+ return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
+ } else {
+ return unwrapped_err_ptr;
+ }
}
}
return result_loc;
@@ -16437,6 +16443,9 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
peer_parent->base.source_instruction->source_node, expected_type, instructions,
peer_parent->peer_count);
+ // the logic below assumes there are no instructions in the new current basic block yet
+ ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base);
+
// In case resolving the parent activates a suspend, do it now
IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
peer_parent->resolved_type, nullptr);
@@ -16445,6 +16454,21 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
{
return parent_result_loc;
}
+ // If the above code generated any instructions in the current basic block, we need
+ // to move them to the peer parent predecessor.
+ ZigList instrs_to_move = {};
+ while (ira->new_irb.current_basic_block->instruction_list.length != 0) {
+ instrs_to_move.append(ira->new_irb.current_basic_block->instruction_list.pop());
+ }
+ if (instrs_to_move.length != 0) {
+ IrBasicBlock *predecessor = peer_parent->base.source_instruction->child->owner_bb;
+ IrInstruction *branch_instruction = predecessor->instruction_list.pop();
+ ir_assert(branch_instruction->value.type->id == ZigTypeIdUnreachable, &phi_instruction->base);
+ while (instrs_to_move.length != 0) {
+ predecessor->instruction_list.append(instrs_to_move.pop());
+ }
+ predecessor->instruction_list.append(branch_instruction);
+ }
}
IrSuspendPosition suspend_pos;
@@ -22213,10 +22237,9 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
}
}
-static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
- IrInstruction *base_ptr = instruction->err_union_ptr->child;
- if (type_is_invalid(base_ptr->value.type))
- return ira->codegen->invalid_instruction;
+static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool initializing)
+{
ZigType *ptr_type = base_ptr->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
@@ -22238,30 +22261,38 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI
if (!ptr_val)
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
- ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+ ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
if (err_union_val == nullptr)
return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
assert(err != nullptr);
- IrInstruction *err_set_val = ir_const(ira, &instruction->base,
- type_entry->data.error_union.err_set_type);
+ IrInstruction *err_set_val = ir_const(ira, source_instr, type_entry->data.error_union.err_set_type);
err_set_val->value.data.x_err_set = err;
err_set_val->value.parent.id = ConstParentIdErrUnionCode;
err_set_val->value.parent.data.p_err_union_code.err_union_val = err_union_val;
- return ir_get_ref(ira, &instruction->base, err_set_val, is_ptr_const, false);
+ return ir_get_ref(ira, source_instr, err_set_val, is_ptr_const, false);
}
}
}
IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, base_ptr);
+ source_instr->scope, source_instr->source_node, base_ptr);
result->value.type = get_pointer_to_type(ira->codegen, type_entry->data.error_union.err_set_type, is_ptr_const);
return result;
}
+static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
+ IrInstructionUnwrapErrCode *instruction)
+{
+ IrInstruction *base_ptr = instruction->err_union_ptr->child;
+ if (type_is_invalid(base_ptr->value.type))
+ return ira->codegen->invalid_instruction;
+ return ir_analyze_unwrap_err_code(ira, &instruction->base, base_ptr, false);
+}
+
static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *base_ptr, bool safety_check_on, bool initializing)
{
@@ -24783,7 +24814,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFrameAddress:
case IrInstructionIdHandle:
case IrInstructionIdTestErr:
- case IrInstructionIdUnwrapErrCode:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
@@ -24846,8 +24876,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {
{
IrInstructionUnwrapErrPayload *unwrap_err_payload_instruction =
(IrInstructionUnwrapErrPayload *)instruction;
- return unwrap_err_payload_instruction->safety_check_on;
+ return unwrap_err_payload_instruction->safety_check_on ||
+ unwrap_err_payload_instruction->initializing;
}
+ case IrInstructionIdUnwrapErrCode:
+ return reinterpret_cast(instruction)->initializing;
case IrInstructionIdErrWrapPayload:
return reinterpret_cast(instruction)->result_loc != nullptr;
case IrInstructionIdErrWrapCode:
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 56a3860199..56862e07a7 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -21,7 +21,7 @@ comptime {
_ = @import("behavior/bugs/1486.zig");
_ = @import("behavior/bugs/1500.zig");
_ = @import("behavior/bugs/1607.zig");
- //_ = @import("behavior/bugs/1851.zig");
+ _ = @import("behavior/bugs/1851.zig");
_ = @import("behavior/bugs/1914.zig");
_ = @import("behavior/bugs/2006.zig");
_ = @import("behavior/bugs/2114.zig");
@@ -41,16 +41,16 @@ comptime {
_ = @import("behavior/byval_arg_var.zig");
//_ = @import("behavior/cancel.zig");
//_ = @import("behavior/cast.zig");
- //_ = @import("behavior/const_slice_child.zig");
+ _ = @import("behavior/const_slice_child.zig");
//_ = @import("behavior/coroutine_await_struct.zig");
//_ = @import("behavior/coroutines.zig");
- //_ = @import("behavior/defer.zig");
+ _ = @import("behavior/defer.zig");
//_ = @import("behavior/enum.zig");
//_ = @import("behavior/enum_with_members.zig");
//_ = @import("behavior/error.zig");
//_ = @import("behavior/eval.zig");
_ = @import("behavior/field_parent_ptr.zig");
- //_ = @import("behavior/fn.zig");
+ _ = @import("behavior/fn.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/for.zig");
//_ = @import("behavior/generics.zig");
@@ -59,13 +59,13 @@ comptime {
//_ = @import("behavior/import.zig");
_ = @import("behavior/incomplete_struct_param_tld.zig");
_ = @import("behavior/inttoptr.zig");
- //_ = @import("behavior/ir_block_deps.zig");
+ _ = @import("behavior/ir_block_deps.zig");
//_ = @import("behavior/math.zig");
//_ = @import("behavior/merge_error_sets.zig");
//_ = @import("behavior/misc.zig");
_ = @import("behavior/namespace_depends_on_compile_var.zig");
_ = @import("behavior/new_stack_call.zig");
- //_ = @import("behavior/null.zig");
+ _ = @import("behavior/null.zig");
//_ = @import("behavior/optional.zig");
//_ = @import("behavior/pointers.zig");
_ = @import("behavior/popcount.zig");
@@ -93,7 +93,7 @@ comptime {
//_ = @import("behavior/union.zig");
_ = @import("behavior/var_args.zig");
_ = @import("behavior/vector.zig");
- //_ = @import("behavior/void.zig");
+ _ = @import("behavior/void.zig");
//_ = @import("behavior/while.zig");
_ = @import("behavior/widening.zig");
}
--
cgit v1.2.3
From 6bf193af192ffaf3465958a243ec8fc8941cfe4d Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 15 Jun 2019 12:28:21 -0400
Subject: better result location semantics with optionals and return locations
somewhere along this branch, #1901 has been fixed.
---
BRANCH_TODO | 5 +-
src/all_types.hpp | 24 +++++++-
src/codegen.cpp | 36 ++++++++----
src/ir.cpp | 114 ++++++++++++++++++++++++++++----------
src/ir_print.cpp | 33 ++++++++---
std/os.zig | 2 +-
std/special/panic.zig | 23 ++++++--
std/special/test_runner.zig | 22 +++-----
test/stage1/behavior.zig | 18 +++---
test/stage1/behavior/cast.zig | 16 +++---
test/stage1/behavior/error.zig | 84 ++++++++++++++--------------
test/stage1/behavior/generics.zig | 26 ++++-----
test/stage1/behavior/optional.zig | 3 +-
test/stage1/behavior/while.zig | 44 +++++++--------
14 files changed, 281 insertions(+), 169 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 79616923bd..011630f315 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -4,10 +4,7 @@ Scratch pad for stuff to do before merging master
uncomment all the behavior tests
diff master branch to make sure
-restore test_runner.zig to master branch
- - also the default panic function and unexpected_error_tracing. see the commit
- that adds this text to BRANCH_TODO file.
- - and std/specia/bootstrap.zig
+restore bootstrap.zig to master
get an empty file compiling successfully (with no panic fn override)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 4497f7bfc7..73726de39b 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2257,7 +2257,8 @@ enum IrInstructionId {
IrInstructionIdHandle,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
- IrInstructionIdTestErr,
+ IrInstructionIdTestErrSrc,
+ IrInstructionIdTestErrGen,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
IrInstructionIdErrWrapCode,
@@ -2292,6 +2293,7 @@ enum IrInstructionId {
IrInstructionIdAlignCast,
IrInstructionIdImplicitCast,
IrInstructionIdResolveResult,
+ IrInstructionIdResultPtr,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
@@ -3082,10 +3084,16 @@ struct IrInstructionAlignOf {
};
// returns true if error, returns false if not error
-struct IrInstructionTestErr {
+struct IrInstructionTestErrSrc {
IrInstruction base;
- IrInstruction *value;
+ IrInstruction *base_ptr;
+};
+
+struct IrInstructionTestErrGen {
+ IrInstruction base;
+
+ IrInstruction *err_union;
};
// Takes an error union pointer, returns a pointer to the error code.
@@ -3596,6 +3604,7 @@ struct IrInstructionImplicitCast {
ResultLoc *result_loc;
};
+// This one is for writing through the result pointer.
struct IrInstructionResolveResult {
IrInstruction base;
@@ -3603,6 +3612,15 @@ struct IrInstructionResolveResult {
IrInstruction *ty;
};
+// This one is when you want to read the value of the result.
+// You have to give the value in case it is comptime.
+struct IrInstructionResultPtr {
+ IrInstruction base;
+
+ ResultLoc *result_loc;
+ IrInstruction *result;
+};
+
struct IrInstructionPtrOfArrayToSlice {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 764f79b130..42670f9005 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1323,7 +1323,9 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
LLVMBuildRetVoid(g->builder);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->add_error_return_trace_addr_fn_val = fn_val;
return fn_val;
@@ -1454,7 +1456,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
LLVMBuildBr(g->builder, loop_block);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->merge_err_ret_traces_fn_val = fn_val;
return fn_val;
@@ -1510,7 +1514,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
LLVMBuildRetVoid(g->builder);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->return_err_fn = fn_val;
return fn_val;
@@ -1638,7 +1644,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
gen_panic(g, msg_slice, err_ret_trace_arg);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->safety_crash_err_fn = fn_val;
return fn_val;
@@ -4353,7 +4361,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
g->cur_fn = prev_cur_fn;
g->cur_fn_val = prev_cur_fn_val;
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
enum_type->data.enumeration.name_function = fn_val;
return fn_val;
@@ -4880,10 +4890,10 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
return overflow_bit;
}
-static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
- ZigType *err_union_type = instruction->value->value.type;
+static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErrGen *instruction) {
+ ZigType *err_union_type = instruction->err_union->value.type;
ZigType *payload_type = err_union_type->data.error_union.payload_type;
- LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);
+ LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union);
LLVMValueRef err_val;
if (type_has_bits(payload_type)) {
@@ -5276,7 +5286,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
g->cur_fn = prev_cur_fn;
g->cur_fn_val = prev_cur_fn_val;
LLVMPositionBuilderAtEnd(g->builder, prev_block);
- LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ if (!g->strip_debug_symbols) {
+ LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
+ }
g->coro_alloc_helper_fn_val = fn_val;
return fn_val;
@@ -5549,10 +5561,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdAllocaGen:
case IrInstructionIdImplicitCast:
case IrInstructionIdResolveResult:
+ case IrInstructionIdResultPtr:
case IrInstructionIdContainerInitList:
case IrInstructionIdSliceSrc:
case IrInstructionIdRef:
case IrInstructionIdBitCastSrc:
+ case IrInstructionIdTestErrSrc:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5635,8 +5649,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);
case IrInstructionIdOverflowOp:
return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
- case IrInstructionIdTestErr:
- return ir_render_test_err(g, executable, (IrInstructionTestErr *)instruction);
+ case IrInstructionIdTestErrGen:
+ return ir_render_test_err(g, executable, (IrInstructionTestErrGen *)instruction);
case IrInstructionIdUnwrapErrCode:
return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
case IrInstructionIdUnwrapErrPayload:
diff --git a/src/ir.cpp b/src/ir.cpp
index 01d824b80c..b6f45a5325 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -756,8 +756,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
return IrInstructionIdOverflowOp;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) {
- return IrInstructionIdTestErr;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrSrc *) {
+ return IrInstructionIdTestErrSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrGen *) {
+ return IrInstructionIdTestErrGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) {
@@ -900,6 +904,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *)
return IrInstructionIdResolveResult;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
+ return IrInstructionIdResultPtr;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {
return IrInstructionIdPtrOfArrayToSlice;
}
@@ -2418,13 +2426,26 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
+static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *base_ptr)
{
- IrInstructionTestErr *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->value = value;
+ IrInstructionTestErrSrc *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->base_ptr = base_ptr;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(base_ptr, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_test_err_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *err_union)
+{
+ IrInstructionTestErrGen *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ira->codegen->builtin_types.entry_bool;
+ instruction->err_union = err_union;
+
+ ir_ref_instruction(err_union, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -2844,6 +2865,18 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
return &instruction->base;
}
+static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc, IrInstruction *result)
+{
+ IrInstructionResultPtr *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+ instruction->result = result;
+
+ ir_ref_instruction(result, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionOpaqueType *instruction = ir_build_instruction(irb, scope, source_node);
@@ -3531,7 +3564,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_gen_defers_for_block(irb, scope, outer_scope, false);
}
- IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
+ IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,
+ return_value);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr);
bool should_inline = ir_should_inline(irb->exec, scope);
IrInstruction *is_comptime;
@@ -3577,8 +3612,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr);
- IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val);
+ IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr);
IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
@@ -5940,8 +5974,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
LValPtr, nullptr);
if (err_val_ptr == irb->codegen->invalid_instruction)
return err_val_ptr;
- IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr);
- IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr);
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
IrInstruction *cond_br_inst;
@@ -6722,7 +6755,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
return err_val_ptr;
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
- IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr);
IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
@@ -7330,8 +7363,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *err_union_val = ir_build_load_ptr(irb, parent_scope, node, err_union_ptr);
- IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);
+ IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr);
IrInstruction *is_comptime;
if (ir_should_inline(irb->exec, parent_scope)) {
@@ -15010,7 +15042,9 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
return result_loc;
ir_assert(result_loc->value.type->id == ZigTypeIdPointer, suspend_source_instr);
ZigType *actual_elem_type = result_loc->value.type->data.pointer.child_type;
- if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
+ if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
+ value_type->id != ZigTypeIdNull)
+ {
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
} else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
if (value_type->id == ZigTypeIdErrorSet) {
@@ -22190,15 +22224,34 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
return result;
}
-static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
- IrInstruction *value = instruction->value->child;
- if (type_is_invalid(value->value.type))
+static IrInstruction *ir_analyze_instruction_result_ptr(IrAnalyze *ira, IrInstructionResultPtr *instruction) {
+ IrInstruction *result = instruction->result->child;
+ if (type_is_invalid(result->value.type))
+ return result;
+
+ if (instruction->result_loc->written && instruction->result_loc->resolved_loc != nullptr &&
+ !instr_is_comptime(result))
+ {
+ IrInstruction *result_ptr = instruction->result_loc->resolved_loc;
+ // Convert the pointer to the result type. They should be the same, except this will resolve
+ // inferred error sets.
+ ZigType *new_ptr_type = get_pointer_to_type(ira->codegen, result->value.type, true);
+ return ir_analyze_ptr_cast(ira, &instruction->base, result_ptr, new_ptr_type, &instruction->base, false);
+ }
+ return ir_get_ref(ira, &instruction->base, result, true, false);
+}
+
+static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErrSrc *instruction) {
+ IrInstruction *base_ptr = instruction->base_ptr->child;
+ if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
+ IrInstruction *value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr);
ZigType *type_entry = value->value.type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id == ZigTypeIdErrorUnion) {
+
+ if (type_entry->id == ZigTypeIdErrorUnion) {
if (instr_is_comptime(value)) {
ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
if (!err_union_val)
@@ -22221,10 +22274,7 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
return ir_const_bool(ira, &instruction->base, false);
}
- IrInstruction *result = ir_build_test_err(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value);
- result->value.type = ira->codegen->builtin_types.entry_bool;
- return result;
+ return ir_build_test_err_gen(ira, &instruction->base, value);
} else if (type_entry->id == ZigTypeIdErrorSet) {
return ir_const_bool(ira, &instruction->base, true);
} else {
@@ -24343,6 +24393,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
case IrInstructionIdAllocaGen:
case IrInstructionIdSliceGen:
case IrInstructionIdRefGen:
+ case IrInstructionIdTestErrGen:
zig_unreachable();
case IrInstructionIdReturn:
@@ -24497,8 +24548,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
case IrInstructionIdOverflowOp:
return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);
- case IrInstructionIdTestErr:
- return ir_analyze_instruction_test_err(ira, (IrInstructionTestErr *)instruction);
+ case IrInstructionIdTestErrSrc:
+ return ir_analyze_instruction_test_err(ira, (IrInstructionTestErrSrc *)instruction);
case IrInstructionIdUnwrapErrCode:
return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);
case IrInstructionIdUnwrapErrPayload:
@@ -24543,6 +24594,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
case IrInstructionIdResolveResult:
return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
+ case IrInstructionIdResultPtr:
+ return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
case IrInstructionIdOpaqueType:
return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
case IrInstructionIdSetAlignStack:
@@ -24672,6 +24725,9 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
continue;
}
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "analyze #%zu\n", old_instruction->debug_id);
+ }
IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
if (new_instruction != nullptr) {
ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
@@ -24808,7 +24864,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdReturnAddress:
case IrInstructionIdFrameAddress:
case IrInstructionIdHandle:
- case IrInstructionIdTestErr:
+ case IrInstructionIdTestErrSrc:
+ case IrInstructionIdTestErrGen:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdPtrCastSrc:
@@ -24860,6 +24917,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdHasDecl:
case IrInstructionIdAllocaSrc:
case IrInstructionIdAllocaGen:
+ case IrInstructionIdResultPtr:
return false;
case IrInstructionIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 4b8b175be0..9750b30e33 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -961,9 +961,15 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct
fprintf(irp->f, ")");
}
-static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
+static void ir_print_test_err_src(IrPrint *irp, IrInstructionTestErrSrc *instruction) {
fprintf(irp->f, "@testError(");
- ir_print_other_instruction(irp, instruction->value);
+ ir_print_other_instruction(irp, instruction->base_ptr);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_test_err_gen(IrPrint *irp, IrInstructionTestErrGen *instruction) {
+ fprintf(irp->f, "@testError(");
+ ir_print_other_instruction(irp, instruction->err_union);
fprintf(irp->f, ")");
}
@@ -976,10 +982,7 @@ static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *i
static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
fprintf(irp->f, "ErrorUnionFieldPayload(");
ir_print_other_instruction(irp, instruction->value);
- fprintf(irp->f, ")");
- if (!instruction->safety_check_on) {
- fprintf(irp->f, " // no safety");
- }
+ fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing);
}
static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
@@ -1301,6 +1304,14 @@ static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *in
fprintf(irp->f, ")");
}
+static void ir_print_result_ptr(IrPrint *irp, IrInstructionResultPtr *instruction) {
+ fprintf(irp->f, "ResultPtr(");
+ ir_print_result_loc(irp, instruction->result_loc);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->result);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
fprintf(irp->f, "@OpaqueType()");
}
@@ -1837,8 +1848,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdOverflowOp:
ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);
break;
- case IrInstructionIdTestErr:
- ir_print_test_err(irp, (IrInstructionTestErr *)instruction);
+ case IrInstructionIdTestErrSrc:
+ ir_print_test_err_src(irp, (IrInstructionTestErrSrc *)instruction);
+ break;
+ case IrInstructionIdTestErrGen:
+ ir_print_test_err_gen(irp, (IrInstructionTestErrGen *)instruction);
break;
case IrInstructionIdUnwrapErrCode:
ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);
@@ -1939,6 +1953,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdResolveResult:
ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
break;
+ case IrInstructionIdResultPtr:
+ ir_print_result_ptr(irp, (IrInstructionResultPtr *)instruction);
+ break;
case IrInstructionIdOpaqueType:
ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
break;
diff --git a/std/os.zig b/std/os.zig
index 3409dcf6c6..a0f8d1f12b 100644
--- a/std/os.zig
+++ b/std/os.zig
@@ -2487,7 +2487,7 @@ pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
/// if this happens the fix is to add the error code to the corresponding
/// switch expression, possibly introduce a new error in the error set, and
/// send a patch to Zig.
-pub const unexpected_error_tracing = false;
+pub const unexpected_error_tracing = builtin.mode == .Debug;
pub const UnexpectedError = error{
/// The Operating System returned an undocumented error code.
diff --git a/std/special/panic.zig b/std/special/panic.zig
index 50dc5e0c65..92e0d9164c 100644
--- a/std/special/panic.zig
+++ b/std/special/panic.zig
@@ -7,8 +7,23 @@ const builtin = @import("builtin");
const std = @import("std");
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
- const stderr = std.io.getStdErr() catch std.process.abort();
- stderr.write("panic: ") catch std.process.abort();
- stderr.write(msg) catch std.process.abort();
- std.process.abort();
+ @setCold(true);
+ switch (builtin.os) {
+ .freestanding => {
+ while (true) {}
+ },
+ .wasi => {
+ std.debug.warn("{}", msg);
+ _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
+ unreachable;
+ },
+ .uefi => {
+ // TODO look into using the debug info and logging helpful messages
+ std.os.abort();
+ },
+ else => {
+ const first_trace_addr = @returnAddress();
+ std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
+ },
+ }
}
diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig
index 001b26ebb0..db01293059 100644
--- a/std/special/test_runner.zig
+++ b/std/special/test_runner.zig
@@ -2,34 +2,28 @@ const std = @import("std");
const io = std.io;
const builtin = @import("builtin");
const test_fn_list = builtin.test_functions;
+const warn = std.debug.warn;
-pub fn main() void {
- const stderr = io.getStdErr() catch std.process.abort();
-
+pub fn main() !void {
var ok_count: usize = 0;
var skip_count: usize = 0;
for (test_fn_list) |test_fn, i| {
- stderr.write("test ") catch std.process.abort();
- stderr.write(test_fn.name) catch std.process.abort();
+ warn("{}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
if (test_fn.func()) |_| {
ok_count += 1;
- stderr.write("...OK\n") catch std.process.abort();
+ warn("OK\n");
} else |err| switch (err) {
error.SkipZigTest => {
skip_count += 1;
- stderr.write("...SKIP\n") catch std.process.abort();
- },
- else => {
- stderr.write("error: ") catch std.process.abort();
- stderr.write(@errorName(err)) catch std.process.abort();
- std.process.abort();
+ warn("SKIP\n");
},
+ else => return err,
}
}
if (ok_count == test_fn_list.len) {
- stderr.write("All tests passed.\n") catch std.process.abort();
+ warn("All tests passed.\n");
} else {
- stderr.write("Some tests skipped.\n") catch std.process.abort();
+ warn("{} passed; {} skipped.\n", ok_count, skip_count);
}
}
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 411785a5c4..90ad30e55c 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -40,46 +40,46 @@ comptime {
//_ = @import("behavior/bugs/920.zig");
_ = @import("behavior/byval_arg_var.zig");
//_ = @import("behavior/cancel.zig");
- _ = @import("behavior/cast.zig"); // TODO
+ _ = @import("behavior/cast.zig");
_ = @import("behavior/const_slice_child.zig");
//_ = @import("behavior/coroutine_await_struct.zig");
//_ = @import("behavior/coroutines.zig");
_ = @import("behavior/defer.zig");
_ = @import("behavior/enum.zig");
_ = @import("behavior/enum_with_members.zig");
- //_ = @import("behavior/error.zig");
+ _ = @import("behavior/error.zig"); // TODO
_ = @import("behavior/eval.zig"); // TODO
_ = @import("behavior/field_parent_ptr.zig");
_ = @import("behavior/fn.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/for.zig");
- _ = @import("behavior/generics.zig"); // TODO
+ _ = @import("behavior/generics.zig");
_ = @import("behavior/hasdecl.zig");
_ = @import("behavior/if.zig");
- //_ = @import("behavior/import.zig");
+ _ = @import("behavior/import.zig");
_ = @import("behavior/incomplete_struct_param_tld.zig");
_ = @import("behavior/inttoptr.zig");
_ = @import("behavior/ir_block_deps.zig");
- //_ = @import("behavior/math.zig");
+ _ = @import("behavior/math.zig");
_ = @import("behavior/merge_error_sets.zig");
_ = @import("behavior/misc.zig"); // TODO
_ = @import("behavior/namespace_depends_on_compile_var.zig");
_ = @import("behavior/new_stack_call.zig");
_ = @import("behavior/null.zig");
_ = @import("behavior/optional.zig"); // TODO
- //_ = @import("behavior/pointers.zig");
+ _ = @import("behavior/pointers.zig");
_ = @import("behavior/popcount.zig");
_ = @import("behavior/ptrcast.zig"); // TODO
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/reflection.zig");
_ = @import("behavior/sizeof_and_typeof.zig");
- //_ = @import("behavior/slice.zig");
+ _ = @import("behavior/slice.zig");
_ = @import("behavior/slicetobytes.zig");
//_ = @import("behavior/struct.zig");
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
_ = @import("behavior/struct_contains_slice_of_itself.zig");
- //_ = @import("behavior/switch.zig");
+ _ = @import("behavior/switch.zig");
//_ = @import("behavior/switch_prong_err_enum.zig");
_ = @import("behavior/switch_prong_implicit_cast.zig");
_ = @import("behavior/syntax.zig");
@@ -87,7 +87,7 @@ comptime {
_ = @import("behavior/truncate.zig");
_ = @import("behavior/try.zig");
_ = @import("behavior/type_info.zig");
- //_ = @import("behavior/typename.zig");
+ _ = @import("behavior/typename.zig");
_ = @import("behavior/undefined.zig");
_ = @import("behavior/underscore.zig");
_ = @import("behavior/union.zig");
diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig
index f659f6d9ae..0a2ffb6c2f 100644
--- a/test/stage1/behavior/cast.zig
+++ b/test/stage1/behavior/cast.zig
@@ -124,14 +124,14 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
return null;
}
-//test "peer type resolution: ?T and T" {
-// expect(peerTypeTAndOptionalT(true, false).? == 0);
-// expect(peerTypeTAndOptionalT(false, false).? == 3);
-// comptime {
-// expect(peerTypeTAndOptionalT(true, false).? == 0);
-// expect(peerTypeTAndOptionalT(false, false).? == 3);
-// }
-//}
+test "peer type resolution: ?T and T" {
+ expect(peerTypeTAndOptionalT(true, false).? == 0);
+ expect(peerTypeTAndOptionalT(false, false).? == 3);
+ comptime {
+ expect(peerTypeTAndOptionalT(true, false).? == 0);
+ expect(peerTypeTAndOptionalT(false, false).? == 3);
+ }
+}
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
if (c) {
return if (b) null else usize(0);
diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig
index babefba6f5..861c500751 100644
--- a/test/stage1/behavior/error.zig
+++ b/test/stage1/behavior/error.zig
@@ -249,48 +249,48 @@ fn intLiteral(str: []const u8) !?i64 {
return error.T;
}
-test "nested error union function call in optional unwrap" {
- const S = struct {
- const Foo = struct {
- a: i32,
- };
-
- fn errorable() !i32 {
- var x: Foo = (try getFoo()) orelse return error.Other;
- return x.a;
- }
-
- fn errorable2() !i32 {
- var x: Foo = (try getFoo2()) orelse return error.Other;
- return x.a;
- }
-
- fn errorable3() !i32 {
- var x: Foo = (try getFoo3()) orelse return error.Other;
- return x.a;
- }
-
- fn getFoo() anyerror!?Foo {
- return Foo{ .a = 1234 };
- }
-
- fn getFoo2() anyerror!?Foo {
- return error.Failure;
- }
-
- fn getFoo3() anyerror!?Foo {
- return null;
- }
- };
- expect((try S.errorable()) == 1234);
- expectError(error.Failure, S.errorable2());
- expectError(error.Other, S.errorable3());
- comptime {
- expect((try S.errorable()) == 1234);
- expectError(error.Failure, S.errorable2());
- expectError(error.Other, S.errorable3());
- }
-}
+//test "nested error union function call in optional unwrap" {
+// const S = struct {
+// const Foo = struct {
+// a: i32,
+// };
+//
+// fn errorable() !i32 {
+// var x: Foo = (try getFoo()) orelse return error.Other;
+// return x.a;
+// }
+//
+// fn errorable2() !i32 {
+// var x: Foo = (try getFoo2()) orelse return error.Other;
+// return x.a;
+// }
+//
+// fn errorable3() !i32 {
+// var x: Foo = (try getFoo3()) orelse return error.Other;
+// return x.a;
+// }
+//
+// fn getFoo() anyerror!?Foo {
+// return Foo{ .a = 1234 };
+// }
+//
+// fn getFoo2() anyerror!?Foo {
+// return error.Failure;
+// }
+//
+// fn getFoo3() anyerror!?Foo {
+// return null;
+// }
+// };
+// expect((try S.errorable()) == 1234);
+// expectError(error.Failure, S.errorable2());
+// expectError(error.Other, S.errorable3());
+// comptime {
+// expect((try S.errorable()) == 1234);
+// expectError(error.Failure, S.errorable2());
+// expectError(error.Other, S.errorable3());
+// }
+//}
test "widen cast integer payload of error union function call" {
const S = struct {
diff --git a/test/stage1/behavior/generics.zig b/test/stage1/behavior/generics.zig
index c514735d17..664b982c21 100644
--- a/test/stage1/behavior/generics.zig
+++ b/test/stage1/behavior/generics.zig
@@ -80,19 +80,19 @@ test "function with return type type" {
expect(list2.prealloc_items.len == 8);
}
-//test "generic struct" {
-// var a1 = GenNode(i32){
-// .value = 13,
-// .next = null,
-// };
-// var b1 = GenNode(bool){
-// .value = true,
-// .next = null,
-// };
-// expect(a1.value == 13);
-// expect(a1.value == a1.getVal());
-// expect(b1.getVal());
-//}
+test "generic struct" {
+ var a1 = GenNode(i32){
+ .value = 13,
+ .next = null,
+ };
+ var b1 = GenNode(bool){
+ .value = true,
+ .next = null,
+ };
+ expect(a1.value == 13);
+ expect(a1.value == a1.getVal());
+ expect(b1.getVal());
+}
fn GenNode(comptime T: type) type {
return struct {
value: T,
diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig
index 0539d1c201..09260c4778 100644
--- a/test/stage1/behavior/optional.zig
+++ b/test/stage1/behavior/optional.zig
@@ -76,6 +76,5 @@ test "unwrap function call with optional pointer return value" {
}
};
S.entry();
- // TODO https://github.com/ziglang/zig/issues/1901
- //comptime S.entry();
+ comptime S.entry();
}
diff --git a/test/stage1/behavior/while.zig b/test/stage1/behavior/while.zig
index 5e486a2495..29ad90ed17 100644
--- a/test/stage1/behavior/while.zig
+++ b/test/stage1/behavior/while.zig
@@ -82,28 +82,28 @@ test "while with else" {
expect(got_else == 1);
}
-//test "while with optional as condition" {
-// numbers_left = 10;
-// var sum: i32 = 0;
-// while (getNumberOrNull()) |value| {
-// sum += value;
-// }
-// expect(sum == 45);
-//}
-//
-//test "while with optional as condition with else" {
-// numbers_left = 10;
-// var sum: i32 = 0;
-// var got_else: i32 = 0;
-// while (getNumberOrNull()) |value| {
-// sum += value;
-// expect(got_else == 0);
-// } else {
-// got_else += 1;
-// }
-// expect(sum == 45);
-// expect(got_else == 1);
-//}
+test "while with optional as condition" {
+ numbers_left = 10;
+ var sum: i32 = 0;
+ while (getNumberOrNull()) |value| {
+ sum += value;
+ }
+ expect(sum == 45);
+}
+
+test "while with optional as condition with else" {
+ numbers_left = 10;
+ var sum: i32 = 0;
+ var got_else: i32 = 0;
+ while (getNumberOrNull()) |value| {
+ sum += value;
+ expect(got_else == 0);
+ } else {
+ got_else += 1;
+ }
+ expect(sum == 45);
+ expect(got_else == 1);
+}
test "while with error union condition" {
numbers_left = 10;
--
cgit v1.2.3
From 9564c05cd5641095d48baf982a372f00bdf02659 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 15 Jun 2019 19:19:13 -0400
Subject: better result location handling of inline loops
---
src/all_types.hpp | 9 ++++
src/codegen.cpp | 1 +
src/ir.cpp | 111 ++++++++++++++++++++++++++++++++--------
src/ir_print.cpp | 9 ++++
test/stage1/behavior.zig | 6 +--
test/stage1/behavior/eval.zig | 20 ++++++--
test/stage1/behavior/struct.zig | 40 +++++++--------
7 files changed, 146 insertions(+), 50 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 73726de39b..49b71e1eed 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2293,6 +2293,7 @@ enum IrInstructionId {
IrInstructionIdAlignCast,
IrInstructionIdImplicitCast,
IrInstructionIdResolveResult,
+ IrInstructionIdResetResult,
IrInstructionIdResultPtr,
IrInstructionIdOpaqueType,
IrInstructionIdSetAlignStack,
@@ -3621,6 +3622,12 @@ struct IrInstructionResultPtr {
IrInstruction *result;
};
+struct IrInstructionResetResult {
+ IrInstruction base;
+
+ ResultLoc *result_loc;
+};
+
struct IrInstructionPtrOfArrayToSlice {
IrInstruction base;
@@ -3639,6 +3646,8 @@ enum ResultLocId {
ResultLocIdBitCast,
};
+// Additions to this struct may need to be handled in
+// ir_reset_result
struct ResultLoc {
ResultLocId id;
bool written;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 42670f9005..4c212c95ab 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5561,6 +5561,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdAllocaGen:
case IrInstructionIdImplicitCast:
case IrInstructionIdResolveResult:
+ case IrInstructionIdResetResult:
case IrInstructionIdResultPtr:
case IrInstructionIdContainerInitList:
case IrInstructionIdSliceSrc:
diff --git a/src/ir.cpp b/src/ir.cpp
index b6f45a5325..d48c013caf 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -166,6 +166,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing);
+static void ir_assert(bool ok, IrInstruction *source_instruction);
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);
static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc);
@@ -904,6 +905,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *)
return IrInstructionIdResolveResult;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) {
+ return IrInstructionIdResetResult;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
return IrInstructionIdResultPtr;
}
@@ -2865,6 +2870,15 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
return &instruction->base;
}
+static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc)
+{
+ IrInstructionResetResult *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
ResultLoc *result_loc, IrInstruction *result)
{
@@ -3540,6 +3554,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
{
ResultLocReturn *result_loc_ret = allocate(1);
result_loc_ret->base.id = ResultLocIdReturn;
+ ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
IrInstruction *return_value;
if (expr_node) {
@@ -3929,7 +3944,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
}
-static ResultLocPeerParent *create_binary_result_peers(IrInstruction *cond_br_inst,
+static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent, IrInstruction *is_comptime)
{
ResultLocPeerParent *peer_parent = allocate(1);
@@ -3948,6 +3963,13 @@ static ResultLocPeerParent *create_binary_result_peers(IrInstruction *cond_br_in
peer_parent->peers[1].base.source_instruction = cond_br_inst;
peer_parent->peers[1].parent = peer_parent;
peer_parent->peers[1].next_bb = endif_block;
+
+ IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();
+ ir_assert(popped_inst == cond_br_inst, cond_br_inst);
+
+ ir_build_reset_result(irb, cond_br_inst->scope, cond_br_inst->source_node, &peer_parent->base);
+ irb->current_basic_block->instruction_list.append(popped_inst);
+
return peer_parent;
}
@@ -3978,8 +4000,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd");
IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, ok_block, end_block, result_loc,
- is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, null_block);
IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, lval, &peer_parent->peers[0].base);
@@ -5006,6 +5028,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
ir_ref_instruction(dest_type, irb->current_basic_block);
result_loc_bit_cast->parent = result_loc;
+ ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base);
+
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone,
&result_loc_bit_cast->base);
@@ -5494,8 +5518,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition,
then_block, else_block, is_comptime);
-
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, then_block);
@@ -5832,11 +5855,14 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
zig_unreachable();
}
-static ResultLocVar *create_var_result_loc(IrInstruction *alloca, ZigVar *var) {
+static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *alloca, ZigVar *var) {
ResultLocVar *result_loc_var = allocate(1);
result_loc_var->base.id = ResultLocIdVar;
result_loc_var->base.source_instruction = alloca;
result_loc_var->var = var;
+
+ ir_build_reset_result(irb, alloca->scope, alloca->source_node, &result_loc_var->base);
+
return result_loc_var;
}
@@ -5844,7 +5870,7 @@ static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *sourc
IrInstruction *init, const char *name_hint, IrInstruction *is_comptime)
{
IrInstruction *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime);
- ResultLocVar *var_result_loc = create_var_result_loc(alloca, var);
+ ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var);
ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base);
ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca);
}
@@ -5907,7 +5933,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
buf_ptr(variable_declaration->symbol), is_comptime);
// Create a result location for the initialization expression.
- ResultLocVar *result_loc_var = create_var_result_loc(alloca, var);
+ ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var);
ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr;
Scope *init_scope = is_comptime_scalar ?
@@ -5983,10 +6009,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
else_block, body_block, is_comptime);
cond_br_inst->is_gen = true;
} else {
- cond_br_inst = is_err; // for the purposes of the source instruction to create_binary_result_peers
+ // for the purposes of the source instruction to ir_build_binary_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
@@ -6085,10 +6112,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
body_block, else_block, is_comptime);
cond_br_inst->is_gen = true;
} else {
- cond_br_inst = is_non_null; // for the purposes of source instruction for create_binary_result_peers
+ // for the purposes of the source instruction to ir_build_binary_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
@@ -6168,10 +6196,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
body_block, else_block, is_comptime);
cond_br_inst->is_gen = true;
} else {
- cond_br_inst = cond_val; // for the source instruction arg to create_binary_result_peers
+ // for the purposes of the source instruction to ir_build_binary_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
@@ -6303,8 +6332,8 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond,
body_block, else_block, is_comptime));
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block, result_loc,
- is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false,
@@ -6683,7 +6712,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null,
then_block, else_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, then_block);
@@ -6765,7 +6794,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);
IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ok_block);
@@ -7093,6 +7122,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value,
check_ranges.items, check_ranges.length, else_prong != nullptr);
+ ir_build_reset_result(irb, scope, node, &peer_parent->base);
+
IrInstruction *br_instruction;
if (cases.length == 0) {
br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime);
@@ -7377,7 +7408,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd");
IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, ok_block, end_block, result_loc,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc,
is_comptime);
ir_set_cursor_at_end_and_append_block(irb, err_block);
@@ -8268,6 +8299,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
// Create a result location indicating there is none - but if one gets created
// it will be properly distributed.
result_loc = no_result_loc();
+ ir_build_reset_result(irb, scope, node, result_loc);
}
IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);
@@ -8521,10 +8553,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// non-allocating. Basically coroutines are not supported right now until they are reworked.
args[3] = ir_build_const_usize(irb, scope, node, 1); // new_size
args[4] = ir_build_const_usize(irb, scope, node, 1); // new_align
- ResultLocNone *result_loc_none = allocate(1);
- result_loc_none->base.id = ResultLocIdNone;
ir_build_call_src(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr,
- nullptr, &result_loc_none->base);
+ nullptr, no_result_loc());
IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
@@ -15082,6 +15112,40 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
return ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr);
}
+static void ir_reset_result(ResultLoc *result_loc) {
+ result_loc->written = false;
+ result_loc->resolved_loc = nullptr;
+ result_loc->gen_instruction = nullptr;
+ result_loc->implicit_elem_type = nullptr;
+ // TODO handle result_loc->scope_elide =
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ zig_unreachable();
+ case ResultLocIdPeerParent: {
+ ResultLocPeerParent *peer_parent = reinterpret_cast(result_loc);
+ peer_parent->skipped = false;
+ peer_parent->done_resuming = false;
+ peer_parent->resolved_type = nullptr;
+ for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
+ ir_reset_result(&peer_parent->peers[i].base);
+ }
+ break;
+ }
+ case ResultLocIdPeer:
+ case ResultLocIdNone:
+ case ResultLocIdVar:
+ case ResultLocIdReturn:
+ case ResultLocIdInstruction:
+ case ResultLocIdBitCast:
+ break;
+ }
+}
+
+static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInstructionResetResult *instruction) {
+ ir_reset_result(instruction->result_loc);
+ return ir_const_void(ira, &instruction->base);
+}
+
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
IrInstruction *async_allocator_inst)
@@ -24594,6 +24658,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
case IrInstructionIdResolveResult:
return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
+ case IrInstructionIdResetResult:
+ return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction);
case IrInstructionIdResultPtr:
return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
case IrInstructionIdOpaqueType:
@@ -24818,6 +24884,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdSliceGen:
case IrInstructionIdOptionalWrap:
case IrInstructionIdVectorToArray:
+ case IrInstructionIdResetResult:
return true;
case IrInstructionIdPhi:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 9750b30e33..b66827fb92 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1304,6 +1304,12 @@ static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *in
fprintf(irp->f, ")");
}
+static void ir_print_reset_result(IrPrint *irp, IrInstructionResetResult *instruction) {
+ fprintf(irp->f, "ResetResult(");
+ ir_print_result_loc(irp, instruction->result_loc);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_result_ptr(IrPrint *irp, IrInstructionResultPtr *instruction) {
fprintf(irp->f, "ResultPtr(");
ir_print_result_loc(irp, instruction->result_loc);
@@ -1953,6 +1959,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdResolveResult:
ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
break;
+ case IrInstructionIdResetResult:
+ ir_print_reset_result(irp, (IrInstructionResetResult *)instruction);
+ break;
case IrInstructionIdResultPtr:
ir_print_result_ptr(irp, (IrInstructionResultPtr *)instruction);
break;
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 90ad30e55c..6aa6ab48cb 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -37,7 +37,7 @@ comptime {
_ = @import("behavior/bugs/718.zig");
_ = @import("behavior/bugs/726.zig");
_ = @import("behavior/bugs/828.zig");
- //_ = @import("behavior/bugs/920.zig");
+ _ = @import("behavior/bugs/920.zig");
_ = @import("behavior/byval_arg_var.zig");
//_ = @import("behavior/cancel.zig");
_ = @import("behavior/cast.zig");
@@ -76,7 +76,7 @@ comptime {
_ = @import("behavior/sizeof_and_typeof.zig");
_ = @import("behavior/slice.zig");
_ = @import("behavior/slicetobytes.zig");
- //_ = @import("behavior/struct.zig");
+ _ = @import("behavior/struct.zig"); // TODO
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
_ = @import("behavior/struct_contains_slice_of_itself.zig");
_ = @import("behavior/switch.zig");
@@ -94,6 +94,6 @@ comptime {
_ = @import("behavior/var_args.zig");
_ = @import("behavior/vector.zig");
_ = @import("behavior/void.zig");
- _ = @import("behavior/while.zig"); // TODO
+ _ = @import("behavior/while.zig");
_ = @import("behavior/widening.zig");
}
diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig
index 595e83b087..49c7380f2b 100644
--- a/test/stage1/behavior/eval.zig
+++ b/test/stage1/behavior/eval.zig
@@ -176,9 +176,9 @@ test "const slice" {
}
}
-//test "try to trick eval with runtime if" {
-// expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
-//}
+test "try to trick eval with runtime if" {
+ expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
+}
fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
comptime var i: usize = 0;
@@ -190,6 +190,17 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
}
}
+//test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
+// var runtime = [1]i32{3};
+// comptime var i: usize = 0;
+// inline while (i < 2) : (i += 1) {
+// const result = if (i == 0) [1]i32{2} else runtime;
+// }
+// comptime {
+// expect(i == 2);
+// }
+//}
+
fn max(comptime T: type, a: T, b: T) T {
if (T == bool) {
return a or b;
@@ -756,8 +767,7 @@ test "comptime bitwise operators" {
test "*align(1) u16 is the same as *align(1:0:2) u16" {
comptime {
expect(*align(1:0:2) u16 == *align(1) u16);
- // TODO add parsing support for this syntax
- //expect(*align(:0:2) u16 == *u16);
+ expect(*align(:0:2) u16 == *u16);
}
}
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index 0ebd0654d0..ccdff3503e 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -529,26 +529,26 @@ test "access to global struct fields" {
expect(g_foo.bar.value == 42);
}
-test "packed struct with fp fields" {
- const S = packed struct {
- data: [3]f32,
-
- pub fn frob(self: *@This()) void {
- self.data[0] += self.data[1] + self.data[2];
- self.data[1] += self.data[0] + self.data[2];
- self.data[2] += self.data[0] + self.data[1];
- }
- };
-
- var s: S = undefined;
- s.data[0] = 1.0;
- s.data[1] = 2.0;
- s.data[2] = 3.0;
- s.frob();
- expectEqual(f32(6.0), s.data[0]);
- expectEqual(f32(11.0), s.data[1]);
- expectEqual(f32(20.0), s.data[2]);
-}
+//test "packed struct with fp fields" {
+// const S = packed struct {
+// data: [3]f32,
+//
+// pub fn frob(self: *@This()) void {
+// self.data[0] += self.data[1] + self.data[2];
+// self.data[1] += self.data[0] + self.data[2];
+// self.data[2] += self.data[0] + self.data[1];
+// }
+// };
+//
+// var s: S = undefined;
+// s.data[0] = 1.0;
+// s.data[1] = 2.0;
+// s.data[2] = 3.0;
+// s.frob();
+// expectEqual(f32(6.0), s.data[0]);
+// expectEqual(f32(11.0), s.data[1]);
+// expectEqual(f32(20.0), s.data[2]);
+//}
test "use within struct scope" {
const S = struct {
--
cgit v1.2.3
From b025193de5b951734e5108e4762e5dc40359431b Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 17 Jun 2019 13:31:19 -0400
Subject: inferred comptime values rather than elided scopes
because of this example:
```zig
export fn entry(b: bool) usize {
var runtime = [1]i32{3};
comptime var i: usize = 0;
inline while (i < 2) : (i += 1) {
const result = if (i == 0) [1]i32{2} else runtime;
}
comptime {
return i;
}
}
```
The problem is that the concept of "resetting" a result location,
introduced in the previous commit, cannot handle elision scopes.
This concept is inherently broken with inline loops.
---
src/all_types.hpp | 14 +-
src/analyze.cpp | 35 +----
src/analyze.hpp | 2 -
src/codegen.cpp | 9 +-
src/ir.cpp | 383 ++++++++++++++++++++++++++++--------------------------
5 files changed, 208 insertions(+), 235 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 49b71e1eed..f63d6a902b 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -203,6 +203,9 @@ enum ConstPtrMut {
// The pointer points to memory that is known only at runtime.
// For example it may point to the initializer value of a variable.
ConstPtrMutRuntimeVar,
+ // The pointer points to memory for which it must be inferred whether the
+ // value is comptime known or not.
+ ConstPtrMutInfer,
};
struct ConstPtrValue {
@@ -1957,7 +1960,6 @@ enum ScopeId {
ScopeIdCompTime,
ScopeIdCoroPrelude,
ScopeIdRuntime,
- ScopeIdElide,
};
struct Scope {
@@ -1971,14 +1973,6 @@ struct Scope {
ScopeId id;
};
-// This scope, when activated, causes all the instructions in the scope to be omitted
-// from the generated code.
-struct ScopeElide {
- Scope base;
-
- bool activated;
-};
-
// This scope comes from global declarations or from
// declarations in a container declaration
// NodeTypeContainerDecl
@@ -2655,6 +2649,7 @@ struct IrInstructionContainerInitFieldsField {
IrInstruction *value;
AstNode *source_node;
TypeStructField *type_struct_field;
+ IrInstruction *result_loc;
};
struct IrInstructionContainerInitFields {
@@ -3655,7 +3650,6 @@ struct ResultLoc {
IrInstruction *source_instruction;
IrInstruction *gen_instruction; // value to store to the result loc
ZigType *implicit_elem_type;
- ScopeElide *scope_elide;
};
struct ResultLocNone {
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 1f9b1ffbed..b39b1e35ca 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -166,12 +166,6 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct
return &scope->base;
}
-ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent) {
- ScopeElide *scope = allocate(1);
- init_scope(g, &scope->base, ScopeIdElide, node, parent);
- return scope;
-}
-
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeSuspend);
ScopeSuspend *scope = allocate(1);
@@ -4187,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
case ConstPtrMutComptimeConst:
hash_val += (uint32_t)4214318515;
break;
+ case ConstPtrMutInfer:
case ConstPtrMutComptimeVar:
hash_val += (uint32_t)1103195694;
break;
@@ -7286,31 +7281,3 @@ void src_assert(bool ok, AstNode *source_node) {
const char *msg = "assertion failed. This is a bug in the Zig compiler.";
stage2_panic(msg, strlen(msg));
}
-
-bool scope_is_elided(Scope *scope) {
- for (;;) {
- switch (scope->id) {
- case ScopeIdElide:
- if (reinterpret_cast(scope)->activated)
- return true;
- // fallthrough
- case ScopeIdBlock:
- case ScopeIdDefer:
- case ScopeIdDeferExpr:
- case ScopeIdVarDecl:
- case ScopeIdLoop:
- case ScopeIdSuspend:
- case ScopeIdCoroPrelude:
- case ScopeIdRuntime:
- scope = scope->parent;
- continue;
- case ScopeIdFnDef:
- case ScopeIdCompTime:
- case ScopeIdDecls:
- case ScopeIdCImport:
- return false;
- }
- zig_unreachable();
- }
-}
-
diff --git a/src/analyze.hpp b/src/analyze.hpp
index c1dd482a7a..8d78ef86e2 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -121,7 +121,6 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
-ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent);
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
@@ -254,6 +253,5 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa
void src_assert(bool ok, AstNode *source_node);
bool is_container(ZigType *type_entry);
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
-bool scope_is_elided(Scope *scope);
#endif
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 4c212c95ab..547840514a 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -722,7 +722,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
case ScopeIdCompTime:
case ScopeIdCoroPrelude:
case ScopeIdRuntime:
- case ScopeIdElide:
return get_di_scope(g, scope->parent);
}
zig_unreachable();
@@ -5761,12 +5760,10 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
continue;
- if (!scope_is_elided(instruction->scope)) {
- if (!g->strip_debug_symbols) {
- set_debug_location(g, instruction);
- }
- instruction->llvm_value = ir_render_instruction(g, executable, instruction);
+ if (!g->strip_debug_symbols) {
+ set_debug_location(g, instruction);
}
+ instruction->llvm_value = ir_render_instruction(g, executable, instruction);
}
current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
}
diff --git a/src/ir.cpp b/src/ir.cpp
index d48c013caf..32f6b4c22a 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -196,6 +196,8 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
IrInstruction *base_ptr, bool safety_check_on, bool initializing);
static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *base_ptr, bool initializing);
+static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *ptr, IrInstruction *uncasted_value);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -3363,7 +3365,6 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco
case ScopeIdSuspend:
case ScopeIdCompTime:
case ScopeIdRuntime:
- case ScopeIdElide:
scope = scope->parent;
continue;
case ScopeIdDeferExpr:
@@ -3420,7 +3421,6 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
case ScopeIdSuspend:
case ScopeIdCompTime:
case ScopeIdRuntime:
- case ScopeIdElide:
scope = scope->parent;
continue;
case ScopeIdDeferExpr:
@@ -5758,15 +5758,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
return irb->codegen->invalid_instruction;
}
- IrInstruction *container_ptr = nullptr;
- if (!ir_should_inline(irb->exec, scope)) {
- src_assert(parent_result_loc->scope_elide == nullptr, node);
- parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
-
- src_assert(parent_result_loc != nullptr, node);
- container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
- node, parent_result_loc, container_type);
- }
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
+ container_type);
size_t field_count = container_init_expr->entries.length;
IrInstructionContainerInitFieldsField *fields = allocate(field_count);
@@ -5777,27 +5770,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
Buf *name = entry_node->data.struct_val_field.name;
AstNode *expr_node = entry_node->data.struct_val_field.expr;
- Scope *val_scope = scope;
- ResultLoc *child_result_loc = nullptr;
- if (container_ptr != nullptr) {
- IrInstruction *field_ptr = ir_build_field_ptr(irb, &parent_result_loc->scope_elide->base,
- expr_node, container_ptr, name, true);
- ResultLocInstruction *result_loc_inst = allocate(1);
- result_loc_inst->base.id = ResultLocIdInstruction;
- result_loc_inst->base.source_instruction = field_ptr;
- ir_ref_instruction(field_ptr, irb->current_basic_block);
- child_result_loc = &result_loc_inst->base;
- val_scope = &parent_result_loc->scope_elide->base;
- }
+ IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, expr_node, container_ptr, name, true);
+ ResultLocInstruction *result_loc_inst = allocate(1);
+ result_loc_inst->base.id = ResultLocIdInstruction;
+ result_loc_inst->base.source_instruction = field_ptr;
+ ir_ref_instruction(field_ptr, irb->current_basic_block);
+ ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
- IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
- child_result_loc);
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
+ &result_loc_inst->base);
if (expr_value == irb->codegen->invalid_instruction)
return expr_value;
fields[i].name = name;
fields[i].value = expr_value;
fields[i].source_node = entry_node;
+ fields[i].result_loc = field_ptr;
}
IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
field_count, fields, container_ptr);
@@ -5812,36 +5800,23 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
}
- IrInstruction *container_ptr = nullptr;
- if (!ir_should_inline(irb->exec, scope)) {
- src_assert(parent_result_loc->scope_elide == nullptr, node);
- parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
-
- container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
- node, parent_result_loc, container_type);
- }
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
+ container_type);
IrInstruction **values = allocate(item_count);
for (size_t i = 0; i < item_count; i += 1) {
AstNode *expr_node = container_init_expr->entries.at(i);
- ResultLoc *child_result_loc = nullptr;
- Scope *val_scope = scope;
- if (container_ptr != nullptr) {
- IrInstruction *elem_index = ir_build_const_usize(irb, &parent_result_loc->scope_elide->base,
- expr_node, i);
- IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &parent_result_loc->scope_elide->base,
- expr_node, container_ptr, elem_index, false, PtrLenSingle, true);
- ResultLocInstruction *result_loc_inst = allocate(1);
- result_loc_inst->base.id = ResultLocIdInstruction;
- result_loc_inst->base.source_instruction = elem_ptr;
- ir_ref_instruction(elem_ptr, irb->current_basic_block);
- child_result_loc = &result_loc_inst->base;
- val_scope = &parent_result_loc->scope_elide->base;
- }
+ IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
+ IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
+ false, PtrLenSingle, true);
+ ResultLocInstruction *result_loc_inst = allocate(1);
+ result_loc_inst->base.id = ResultLocIdInstruction;
+ result_loc_inst->base.source_instruction = elem_ptr;
+ ir_ref_instruction(elem_ptr, irb->current_basic_block);
- IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
- child_result_loc);
+ IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
+ &result_loc_inst->base);
if (expr_value == irb->codegen->invalid_instruction)
return expr_value;
@@ -8651,8 +8626,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
IrBasicBlock *bb = exec->basic_block_list.at(0);
for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
IrInstruction *instruction = bb->instruction_list.at(i);
- if (scope_is_elided(instruction->scope))
- continue;
if (instruction->id == IrInstructionIdReturn) {
IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;
IrInstruction *value = ret_inst->value;
@@ -12745,9 +12718,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
return ira->codegen->invalid_instruction;
}
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
- ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
- {
+ if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
if (pointee->special != ConstValSpecialRuntime) {
IrInstruction *result = ir_const(ira, source_instruction, child_type);
@@ -14487,7 +14458,25 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
}
if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {
- if (var->mem_slot_index != SIZE_MAX) {
+ // Resolve ConstPtrMutInfer
+ if (var->gen_is_const) {
+ var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ } else if (is_comptime_var) {
+ var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
+ } else {
+ // we need a runtime ptr but we have a comptime val.
+ // since it's a comptime val there are no instructions for it.
+ // we memcpy the init value here
+ IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr);
+ // If this assertion trips, something is wrong with the IR instructions, because
+ // we expected the above deref to return a constant value, but it created a runtime
+ // instruction.
+ assert(deref->value.special != ConstValSpecialRuntime);
+ var_ptr->value.special = ConstValSpecialRuntime;
+ ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref);
+ }
+
+ if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {
assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);
@@ -14818,9 +14807,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
pointee->special = ConstValSpecialUndef;
IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint);
- result->base.value.special = force_comptime ? ConstValSpecialStatic : ConstValSpecialRuntime;
+ result->base.value.special = ConstValSpecialStatic;
result->base.value.data.x_ptr.special = ConstPtrSpecialRef;
- result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutRuntimeVar;
+ result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
result->base.value.data.x_ptr.data.ref.pointee = pointee;
if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
@@ -15109,7 +15098,10 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
if (type_is_invalid(implicit_elem_type))
return ira->codegen->invalid_instruction;
- return ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr);
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr);
+ if (result_loc != nullptr)
+ return result_loc;
+ zig_panic("TODO");
}
static void ir_reset_result(ResultLoc *result_loc) {
@@ -15431,7 +15423,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
return ira->codegen->invalid_instruction;
}
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar ||
+ ptr->value.data.x_ptr.mut == ConstPtrMutInfer)
+ {
if (instr_is_comptime(value)) {
ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
if (dest_val == nullptr)
@@ -15451,12 +15445,16 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
return ir_const_void(ira, source_instr);
}
}
- ir_add_error(ira, source_instr,
- buf_sprintf("cannot store runtime value in compile time variable"));
- ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
- dest_val->type = ira->codegen->builtin_types.entry_invalid;
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ ptr->value.special = ConstValSpecialRuntime;
+ } else {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("cannot store runtime value in compile time variable"));
+ ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
+ dest_val->type = ira->codegen->builtin_types.entry_invalid;
- return ira->codegen->invalid_instruction;
+ return ira->codegen->invalid_instruction;
+ }
}
}
@@ -17091,6 +17089,81 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
return ira->codegen->invalid_instruction;
}
+static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
+{
+ switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes: {
+ IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
+ return ir_get_ref(ira, source_instr, elem, false, false);
+ }
+ case OnePossibleValueNo:
+ break;
+ }
+ assert(struct_ptr->value.type->id == ZigTypeIdPointer);
+ bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
+ uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
+ uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
+ uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
+ uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
+ get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
+ bool is_const = struct_ptr->value.type->data.pointer.is_const;
+ bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
+ is_const, is_volatile, PtrLenSingle, align_bytes,
+ (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
+ (uint32_t)host_int_bytes_for_result_type, false);
+ if (instr_is_comptime(struct_ptr)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
+ if (!ptr_val)
+ return ira->codegen->invalid_instruction;
+
+ if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
+ ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
+ if (struct_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (type_is_invalid(struct_val->type))
+ return ira->codegen->invalid_instruction;
+ if (struct_val->special == ConstValSpecialUndef && initializing) {
+ struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);
+ struct_val->special = ConstValSpecialStatic;
+ for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
+ ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
+ field_val->special = ConstValSpecialUndef;
+ field_val->type = struct_type->data.structure.fields[i].type_entry;
+ ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
+ if (parent != nullptr) {
+ parent->id = ConstParentIdStruct;
+ parent->data.p_struct.struct_val = struct_val;
+ parent->data.p_struct.field_index = i;
+ }
+ }
+ }
+ IrInstruction *result;
+ if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, struct_ptr, field);
+ result->value.type = ptr_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, source_instr, ptr_type);
+ }
+ ConstExprValue *const_val = &result->value;
+ const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
+ const_val->data.x_ptr.mut = struct_ptr->value.data.x_ptr.mut;
+ const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
+ const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
+ return result;
+ }
+ }
+ IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
+ struct_ptr, field);
+ result->value.type = ptr_type;
+ return result;
+}
+
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
{
@@ -17101,59 +17174,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
assert(container_ptr->value.type->id == ZigTypeIdPointer);
- bool is_const = container_ptr->value.type->data.pointer.is_const;
- bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
if (bare_type->id == ZigTypeIdStruct) {
TypeStructField *field = find_struct_type_field(bare_type, field_name);
- if (field) {
- switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
- case OnePossibleValueInvalid:
- return ira->codegen->invalid_instruction;
- case OnePossibleValueYes: {
- IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
- return ir_get_ref(ira, source_instr, elem, false, false);
- }
- case OnePossibleValueNo:
- break;
- }
- bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
- uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
- uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
- uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes;
- uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
- get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes;
- if (instr_is_comptime(container_ptr)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
- if (!ptr_val)
- return ira->codegen->invalid_instruction;
-
- if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
- if (struct_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (type_is_invalid(struct_val->type))
- return ira->codegen->invalid_instruction;
- ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
- is_const, is_volatile, PtrLenSingle, align_bytes,
- (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
- (uint32_t)host_int_bytes_for_result_type, false);
- IrInstruction *result = ir_const(ira, source_instr, ptr_type);
- ConstExprValue *const_val = &result->value;
- const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
- const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
- const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
- const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
- return result;
- }
- }
- IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
- container_ptr, field);
- result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
- PtrLenSingle,
- align_bytes,
- (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
- host_int_bytes_for_result_type, false);
- return result;
+ if (field != nullptr) {
+ return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
} else {
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
source_instr, container_ptr, container_type);
@@ -17162,6 +17186,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
source_instr, container_ptr, container_type);
} else if (bare_type->id == ZigTypeIdUnion) {
+ bool is_const = container_ptr->value.type->data.pointer.is_const;
+ bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
+
TypeUnionField *field = find_union_type_field(bare_type, field_name);
if (field) {
if (instr_is_comptime(container_ptr)) {
@@ -18849,7 +18876,7 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
- IrInstruction *old_result_loc)
+ IrInstruction *result_loc)
{
Error err;
assert(container_type->id == ZigTypeIdUnion);
@@ -18905,21 +18932,17 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
return result;
}
- ir_assert(old_result_loc != nullptr, instruction);
- IrInstruction *result_loc = old_result_loc->child;
- if (type_is_invalid(result_loc->value.type))
- return result_loc;
return ir_get_deref(ira, instruction, result_loc, nullptr);
}
static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
- IrInstruction *old_result_loc)
+ IrInstruction *result_loc)
{
Error err;
if (container_type->id == ZigTypeIdUnion) {
return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
- fields, old_result_loc);
+ fields, result_loc);
}
if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
ir_add_error(ira, instruction,
@@ -18936,20 +18959,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
IrInstruction *first_non_const_instruction = nullptr;
AstNode **field_assign_nodes = allocate(actual_field_count);
+ ZigList const_ptrs = {};
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
|| type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
- ConstExprValue const_val = {};
- const_val.special = ConstValSpecialStatic;
- const_val.type = container_type;
- // const_val.global_refs = allocate(1);
- const_val.data.x_struct.fields = create_const_vals(actual_field_count);
+
+ // Here we iterate over the fields that have been initialized, and emit
+ // compile errors for missing fields and duplicate fields.
+ // It is only now that we find out whether the struct initialization can be a comptime
+ // value, but we have already emitted runtime instructions for the fields that
+ // were initialized with runtime values, and have omitted instructions that would have
+ // initialized fields with comptime values.
+ // So now we must clean up this situation. If it turns out the struct initialization can
+ // be a comptime value, overwrite ConstPtrMutInfer with ConstPtrMutComptimeConst.
+ // Otherwise, we must emit instructions to runtime-initialize the fields that have
+ // comptime-known values.
+
for (size_t i = 0; i < instr_field_count; i += 1) {
IrInstructionContainerInitFieldsField *field = &fields[i];
- IrInstruction *field_value = field->value->child;
- if (type_is_invalid(field_value->value.type))
+ IrInstruction *field_result_loc = field->result_loc->child;
+ if (type_is_invalid(field_result_loc->value.type))
return ira->codegen->invalid_instruction;
TypeStructField *type_field = find_struct_type_field(container_type, field->name);
@@ -18963,10 +18994,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
if (type_is_invalid(type_field->type_entry))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
- if (casted_field_value == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
-
size_t field_index = type_field->src_index;
AstNode *existing_assign_node = field_assign_nodes[field_index];
if (existing_assign_node) {
@@ -18976,23 +19003,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
}
field_assign_nodes[field_index] = field->source_node;
- if (const_val.special == ConstValSpecialStatic) {
- if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
- ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
- if (!field_val)
- return ira->codegen->invalid_instruction;
-
- copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true);
- } else {
- first_non_const_instruction = casted_field_value;
- const_val.special = ConstValSpecialRuntime;
- }
+ if (instr_is_comptime(field_result_loc) &&
+ field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
+ {
+ const_ptrs.append(field_result_loc);
+ } else {
+ first_non_const_instruction = field_result_loc;
}
}
bool any_missing = false;
for (size_t i = 0; i < actual_field_count; i += 1) {
- if (field_assign_nodes[i]) continue;
+ if (field_assign_nodes[i] != nullptr) continue;
// look for a default field value
TypeStructField *field = &container_type->data.structure.fields[i];
@@ -19018,44 +19040,41 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
copy_const_val(&runtime_inst->value, field->init_val, true);
- if (const_val.special == ConstValSpecialStatic) {
- copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);
+ IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
+ container_type, true);
+ ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst);
+ if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+ const_ptrs.append(field_ptr);
+ } else {
+ first_non_const_instruction = result_loc;
}
}
if (any_missing)
return ira->codegen->invalid_instruction;
- if (const_val.special == ConstValSpecialStatic) {
- IrInstruction *result = ir_const(ira, instruction, nullptr);
- ConstExprValue *out_val = &result->value;
- copy_const_val(out_val, &const_val, false);
- out_val->type = container_type;
-
- for (size_t i = 0; i < instr_field_count; i += 1) {
- ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
- ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdStruct;
- parent->data.p_struct.field_index = i;
- parent->data.p_struct.struct_val = out_val;
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (const_ptrs.length == actual_field_count) {
+ result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ } else {
+ result_loc->value.special = ConstValSpecialRuntime;
+ for (size_t i = 0; i < const_ptrs.length; i += 1) {
+ IrInstruction *field_result_loc = const_ptrs.at(i);
+ IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
+ field_result_loc->value.special = ConstValSpecialRuntime;
+ ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref);
}
}
-
- return result;
}
- if (is_comptime) {
+ IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
+
+ if (is_comptime && !instr_is_comptime(result)) {
ir_add_error_node(ira, first_non_const_instruction->source_node,
buf_sprintf("unable to evaluate constant expression"));
return ira->codegen->invalid_instruction;
}
-
- ir_assert(old_result_loc != nullptr, instruction);
- IrInstruction *result_loc = old_result_loc->child;
- if (type_is_invalid(result_loc->value.type))
- return result_loc;
- return ir_get_deref(ira, instruction, result_loc, nullptr);
+ return result;
}
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
@@ -19074,8 +19093,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
buf_sprintf("expected array type or [_], found slice"));
return ira->codegen->invalid_instruction;
} else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
- return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr,
- instruction->result_loc);
+ ir_assert(instruction->result_loc != nullptr, &instruction->base);
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return result_loc;
+ return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
} else if (container_type->id == ZigTypeIdArray) {
// array is same as slice init but we make a compile error if the length is wrong
ZigType *child_type;
@@ -19199,8 +19221,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir
if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
+ ir_assert(instruction->result_loc != nullptr, &instruction->base);
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return result_loc;
+
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
- instruction->field_count, instruction->fields, instruction->result_loc);
+ instruction->field_count, instruction->fields, result_loc);
}
static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
@@ -24390,17 +24417,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
- bool want_resolve_result;
- if (instruction->result_loc->written) {
- if (instruction->result_loc->scope_elide != nullptr && instr_is_comptime(value)) {
- want_resolve_result = true;
- instruction->result_loc->scope_elide->activated = true;
- } else {
- want_resolve_result = false;
- }
- } else {
- want_resolve_result = true;
- }
+ bool want_resolve_result = !instruction->result_loc->written;
if (want_resolve_result) {
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
value->value.type, value);
--
cgit v1.2.3
From e27da17ff2cc45c93ab95defd937fd8038751b51 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 18 Jun 2019 17:07:27 -0400
Subject: back to many behavioral tests passing
---
src/codegen.cpp | 4 +---
src/ir.cpp | 2 +-
test/stage1/behavior.zig | 4 ++--
test/stage1/behavior/cast.zig | 36 ++++++++++++++++++------------------
test/stage1/behavior/enum.zig | 32 ++++++++++++++++----------------
test/stage1/behavior/error.zig | 16 ++++++++--------
test/stage1/behavior/struct.zig | 12 ++++++------
7 files changed, 52 insertions(+), 54 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 547840514a..dc2a4f55df 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2017,11 +2017,9 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
render_const_val_global(g, &instruction->value, "");
ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, get_llvm_type(g, ptr_type), "");
- } else if (get_codegen_ptr_type(instruction->value.type) != nullptr) {
+ } else {
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value,
get_llvm_type(g, instruction->value.type), "");
- } else {
- instruction->llvm_value = instruction->value.global_refs->llvm_value;
}
assert(instruction->llvm_value);
}
diff --git a/src/ir.cpp b/src/ir.cpp
index 90d79995e1..4d2221ab39 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -14999,7 +14999,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
return parent_result_loc;
}
// because is_comptime is false, we mark this a runtime pointer
- parent_result_loc->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
+ parent_result_loc->value.special = ConstValSpecialRuntime;
result_loc->written = true;
result_loc->resolved_loc = parent_result_loc;
return result_loc->resolved_loc;
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 6aa6ab48cb..ccbec6849a 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -40,12 +40,12 @@ comptime {
_ = @import("behavior/bugs/920.zig");
_ = @import("behavior/byval_arg_var.zig");
//_ = @import("behavior/cancel.zig");
- _ = @import("behavior/cast.zig");
+ _ = @import("behavior/cast.zig"); // TODO
_ = @import("behavior/const_slice_child.zig");
//_ = @import("behavior/coroutine_await_struct.zig");
//_ = @import("behavior/coroutines.zig");
_ = @import("behavior/defer.zig");
- _ = @import("behavior/enum.zig");
+ _ = @import("behavior/enum.zig"); // TODO
_ = @import("behavior/enum_with_members.zig");
_ = @import("behavior/error.zig"); // TODO
_ = @import("behavior/eval.zig"); // TODO
diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig
index 0a2ffb6c2f..c148523a72 100644
--- a/test/stage1/behavior/cast.zig
+++ b/test/stage1/behavior/cast.zig
@@ -165,10 +165,10 @@ fn castToOptionalSlice() ?[]const u8 {
return "hi";
}
-test "implicitly cast from [0]T to anyerror![]T" {
- testCastZeroArrayToErrSliceMut();
- comptime testCastZeroArrayToErrSliceMut();
-}
+//test "implicitly cast from [0]T to anyerror![]T" {
+// testCastZeroArrayToErrSliceMut();
+// comptime testCastZeroArrayToErrSliceMut();
+//}
fn testCastZeroArrayToErrSliceMut() void {
expect((gimmeErrOrSlice() catch unreachable).len == 0);
@@ -178,20 +178,20 @@ fn gimmeErrOrSlice() anyerror![]u8 {
return [_]u8{};
}
-test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
- {
- var data = "hi";
- const slice = data[0..];
- expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
- expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
- }
- comptime {
- var data = "hi";
- const slice = data[0..];
- expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
- expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
- }
-}
+//test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
+// {
+// var data = "hi";
+// const slice = data[0..];
+// expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+// expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+// }
+// comptime {
+// var data = "hi";
+// const slice = data[0..];
+// expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+// expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+// }
+//}
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
if (a) {
return [_]u8{};
diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig
index 51f4f0e196..e06a075974 100644
--- a/test/stage1/behavior/enum.zig
+++ b/test/stage1/behavior/enum.zig
@@ -1,22 +1,22 @@
const expect = @import("std").testing.expect;
const mem = @import("std").mem;
-test "enum type" {
- const foo1 = Foo{ .One = 13 };
- const foo2 = Foo{
- .Two = Point{
- .x = 1234,
- .y = 5678,
- },
- };
- const bar = Bar.B;
-
- expect(bar == Bar.B);
- expect(@memberCount(Foo) == 3);
- expect(@memberCount(Bar) == 4);
- expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
- expect(@sizeOf(Bar) == 1);
-}
+//test "enum type" {
+// const foo1 = Foo{ .One = 13 };
+// const foo2 = Foo{
+// .Two = Point{
+// .x = 1234,
+// .y = 5678,
+// },
+// };
+// const bar = Bar.B;
+//
+// expect(bar == Bar.B);
+// expect(@memberCount(Foo) == 3);
+// expect(@memberCount(Bar) == 4);
+// expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
+// expect(@sizeOf(Bar) == 1);
+//}
test "enum as return value" {
switch (returnAnInt(13)) {
diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig
index 861c500751..1f8f8b36e4 100644
--- a/test/stage1/behavior/error.zig
+++ b/test/stage1/behavior/error.zig
@@ -130,10 +130,10 @@ fn testExplicitErrorSetCast(set1: Set1) void {
expect(y == error.A);
}
-test "comptime test error for empty error set" {
- testComptimeTestErrorEmptySet(1234);
- comptime testComptimeTestErrorEmptySet(1234);
-}
+//test "comptime test error for empty error set" {
+// testComptimeTestErrorEmptySet(1234);
+// comptime testComptimeTestErrorEmptySet(1234);
+//}
const EmptyErrorSet = error{};
@@ -204,10 +204,10 @@ fn foo2(f: fn () anyerror!void) void {
fn bar2() (error{}!void) {}
-test "error: Zero sized error set returned with value payload crash" {
- _ = foo3(0) catch {};
- _ = comptime foo3(0) catch {};
-}
+//test "error: Zero sized error set returned with value payload crash" {
+// _ = foo3(0) catch {};
+// _ = comptime foo3(0) catch {};
+//}
const Error = error{};
fn foo3(b: usize) Error!usize {
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index ccdff3503e..a08dec5359 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -522,12 +522,12 @@ const S0 = struct {
}
};
-var g_foo: S0 = S0.init();
-
-test "access to global struct fields" {
- g_foo.bar.value = 42;
- expect(g_foo.bar.value == 42);
-}
+//var g_foo: S0 = S0.init();
+//
+//test "access to global struct fields" {
+// g_foo.bar.value = 42;
+// expect(g_foo.bar.value == 42);
+//}
//test "packed struct with fp fields" {
// const S = packed struct {
--
cgit v1.2.3
From fce2d2d18be279359dcd75254506d46085c59aaf Mon Sep 17 00:00:00 2001
From: Shawn Landden
Date: Tue, 18 Jun 2019 17:28:49 -0500
Subject: stage1: add support for @mulAdd fused-multiply-add for floats and
vectors of floats
Not all of the softfloat library is being built....
Vector support is very buggy at the moment, but should work when the bugs are fixed.
(as I had the same code working with another vector function, that hasn't been merged yet).
---
CMakeLists.txt | 2 +
doc/langref.html.in | 7 ++
src/all_types.hpp | 13 +++
src/analyze.cpp | 7 +-
src/codegen.cpp | 46 ++++++++++-
src/ir.cpp | 171 ++++++++++++++++++++++++++++++++++++++++
src/ir_print.cpp | 19 +++++
test/stage1/behavior/muladd.zig | 34 ++++++++
8 files changed, 292 insertions(+), 7 deletions(-)
create mode 100644 test/stage1/behavior/muladd.zig
(limited to 'src/codegen.cpp')
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d6f8176e40..6a06afc9fa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -389,6 +389,8 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"
+ "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c"
+ "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 5ddd572e51..9b95946256 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -6259,6 +6259,13 @@ comptime {
This function is only valid within function scope.
+ {#header_close#}
+ {#header_open|@mulAdd#}
+ {#syntax#}@mulAdd(comptime T: type, a: T, b: T, c: T) T{#endsyntax#}
+
+ Fused multiply add (for floats), similar to {#syntax#}(a * b) + c{#endsyntax#}, except
+ only rounds once, and is thus more accurate.
+
{#header_close#}
{#header_open|@byteSwap#}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 5aa1c78ea1..83df71b95f 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1406,6 +1406,7 @@ enum BuiltinFnId {
BuiltinFnIdSubWithOverflow,
BuiltinFnIdMulWithOverflow,
BuiltinFnIdShlWithOverflow,
+ BuiltinFnIdMulAdd,
BuiltinFnIdCInclude,
BuiltinFnIdCDefine,
BuiltinFnIdCUndef,
@@ -1554,6 +1555,7 @@ enum ZigLLVMFnId {
ZigLLVMFnIdClz,
ZigLLVMFnIdPopCount,
ZigLLVMFnIdOverflowArithmetic,
+ ZigLLVMFnIdFMA,
ZigLLVMFnIdFloor,
ZigLLVMFnIdCeil,
ZigLLVMFnIdSqrt,
@@ -1584,6 +1586,7 @@ struct ZigLLVMFnKey {
} pop_count;
struct {
uint32_t bit_count;
+ uint32_t vector_len; // 0 means not a vector
} floating;
struct {
AddSubMul add_sub_mul;
@@ -2235,6 +2238,7 @@ enum IrInstructionId {
IrInstructionIdHandle,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
+ IrInstructionIdMulAdd,
IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
@@ -3038,6 +3042,15 @@ struct IrInstructionOverflowOp {
ZigType *result_ptr_type;
};
+struct IrInstructionMulAdd {
+ IrInstruction base;
+
+ IrInstruction *type_value;
+ IrInstruction *op1;
+ IrInstruction *op2;
+ IrInstruction *op3;
+};
+
struct IrInstructionAlignOf {
IrInstruction base;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index c7e35367c3..bff740cd52 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -5737,11 +5737,11 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
case ZigLLVMFnIdPopCount:
return (uint32_t)(x.data.clz.bit_count) * (uint32_t)101195049;
case ZigLLVMFnIdFloor:
- return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1899859168;
case ZigLLVMFnIdCeil:
- return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
case ZigLLVMFnIdSqrt:
- return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
+ case ZigLLVMFnIdFMA:
+ return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
+ (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025);
case ZigLLVMFnIdBswap:
return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
case ZigLLVMFnIdBitReverse:
@@ -5772,6 +5772,7 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
case ZigLLVMFnIdFloor:
case ZigLLVMFnIdCeil:
case ZigLLVMFnIdSqrt:
+ case ZigLLVMFnIdFMA:
return a.data.floating.bit_count == b.data.floating.bit_count;
case ZigLLVMFnIdOverflowArithmetic:
return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 3dd6995c61..6691652a5e 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -807,31 +807,51 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSu
}
static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id) {
- assert(type_entry->id == ZigTypeIdFloat);
+ assert(type_entry->id == ZigTypeIdFloat ||
+ type_entry->id == ZigTypeIdVector);
+
+ bool is_vector = (type_entry->id == ZigTypeIdVector);
+ ZigType *float_type = is_vector ? type_entry->data.vector.elem_type : type_entry;
ZigLLVMFnKey key = {};
key.id = fn_id;
- key.data.floating.bit_count = (uint32_t)type_entry->data.floating.bit_count;
+ key.data.floating.bit_count = (uint32_t)float_type->data.floating.bit_count;
+ key.data.floating.vector_len = is_vector ? (uint32_t)type_entry->data.vector.len : 0;
auto existing_entry = g->llvm_fn_table.maybe_get(key);
if (existing_entry)
return existing_entry->value;
const char *name;
+ uint32_t num_args;
if (fn_id == ZigLLVMFnIdFloor) {
name = "floor";
+ num_args = 1;
} else if (fn_id == ZigLLVMFnIdCeil) {
name = "ceil";
+ num_args = 1;
} else if (fn_id == ZigLLVMFnIdSqrt) {
name = "sqrt";
+ num_args = 1;
+ } else if (fn_id == ZigLLVMFnIdFMA) {
+ name = "fma";
+ num_args = 3;
} else {
zig_unreachable();
}
char fn_name[64];
- sprintf(fn_name, "llvm.%s.f%" ZIG_PRI_usize "", name, type_entry->data.floating.bit_count);
+ if (is_vector)
+ sprintf(fn_name, "llvm.%s.v%" PRIu32 "f%" PRIu32, name, key.data.floating.vector_len, key.data.floating.bit_count);
+ else
+ sprintf(fn_name, "llvm.%s.f%" PRIu32, name, key.data.floating.bit_count);
LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry);
- LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, &float_type_ref, 1, false);
+ LLVMTypeRef return_elem_types[3] = {
+ float_type_ref,
+ float_type_ref,
+ float_type_ref,
+ };
+ LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, num_args, false);
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
assert(LLVMGetIntrinsicID(fn_val));
@@ -5437,6 +5457,21 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
}
+static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) {
+ LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
+ LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
+ LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
+ assert(instruction->base.value.type->id == ZigTypeIdFloat ||
+ instruction->base.value.type->id == ZigTypeIdVector);
+ LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdFMA);
+ LLVMValueRef args[3] = {
+ op1,
+ op2,
+ op3,
+ };
+ return LLVMBuildCall(g->builder, fn_val, args, 3, "");
+}
+
static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
LLVMValueRef op = ir_llvm_value(g, instruction->op);
ZigType *int_type = instruction->base.value.type;
@@ -5781,6 +5816,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
case IrInstructionIdSqrt:
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdMulAdd:
+ return ir_render_mul_add(g, executable, (IrInstructionMulAdd *)instruction);
case IrInstructionIdArrayToVector:
return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
case IrInstructionIdVectorToArray:
@@ -7398,6 +7435,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);
+ create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
diff --git a/src/ir.cpp b/src/ir.cpp
index 5c09e48b2d..c2c6cb6154 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -747,6 +747,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) {
return IrInstructionIdTestErr;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionMulAdd *) {
+ return IrInstructionIdMulAdd;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) {
return IrInstructionIdUnwrapErrCode;
}
@@ -2308,6 +2312,22 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_mul_add(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, IrInstruction *op3) {
+ IrInstructionMulAdd *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->type_value = type_value;
+ instruction->op1 = op1;
+ instruction->op2 = op2;
+ instruction->op3 = op3;
+
+ ir_ref_instruction(type_value, irb->current_basic_block);
+ ir_ref_instruction(op1, irb->current_basic_block);
+ ir_ref_instruction(op2, irb->current_basic_block);
+ ir_ref_instruction(op3, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
IrInstructionAlignOf *instruction = ir_build_instruction(irb, scope, source_node);
instruction->type_value = type_value;
@@ -4028,6 +4048,33 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *
return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr);
}
+static IrInstruction *ir_gen_mul_add(IrBuilder *irb, Scope *scope, AstNode *node) {
+ assert(node->type == NodeTypeFnCallExpr);
+
+ AstNode *type_node = node->data.fn_call_expr.params.at(0);
+ AstNode *op1_node = node->data.fn_call_expr.params.at(1);
+ AstNode *op2_node = node->data.fn_call_expr.params.at(2);
+ AstNode *op3_node = node->data.fn_call_expr.params.at(3);
+
+ IrInstruction *type_value = ir_gen_node(irb, type_node, scope);
+ if (type_value == irb->codegen->invalid_instruction)
+ return irb->codegen->invalid_instruction;
+
+ IrInstruction *op1 = ir_gen_node(irb, op1_node, scope);
+ if (op1 == irb->codegen->invalid_instruction)
+ return irb->codegen->invalid_instruction;
+
+ IrInstruction *op2 = ir_gen_node(irb, op2_node, scope);
+ if (op2 == irb->codegen->invalid_instruction)
+ return irb->codegen->invalid_instruction;
+
+ IrInstruction *op3 = ir_gen_node(irb, op3_node, scope);
+ if (op3 == irb->codegen->invalid_instruction)
+ return irb->codegen->invalid_instruction;
+
+ return ir_build_mul_add(irb, scope, node, type_value, op1, op2, op3);
+}
+
static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *node) {
for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) {
if (it_scope->id == ScopeIdDecls) {
@@ -4687,6 +4734,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval);
case BuiltinFnIdShlWithOverflow:
return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval);
+ case BuiltinFnIdMulAdd:
+ return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval);
case BuiltinFnIdTypeName:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -21185,6 +21234,125 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
return result;
}
+static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type,
+ ConstExprValue *op1, ConstExprValue *op2, ConstExprValue *op3, ConstExprValue *out_val) {
+ if (float_type->id == ZigTypeIdComptimeFloat) {
+ f128M_mulAdd(&out_val->data.x_bigfloat.value, &op1->data.x_bigfloat.value, &op2->data.x_bigfloat.value,
+ &op3->data.x_bigfloat.value);
+ } else if (float_type->id == ZigTypeIdFloat) {
+ switch (float_type->data.floating.bit_count) {
+ case 16:
+ out_val->data.x_f16 = f16_mulAdd(op1->data.x_f16, op2->data.x_f16, op3->data.x_f16);
+ break;
+ case 32:
+ out_val->data.x_f32 = fmaf(op1->data.x_f32, op2->data.x_f32, op3->data.x_f32);
+ break;
+ case 64:
+ out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64);
+ break;
+ case 128:
+ f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128);
+ break;
+ default:
+ zig_unreachable();
+ }
+ } else {
+ zig_unreachable();
+ }
+}
+
+static IrInstruction *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstructionMulAdd *instruction) {
+ IrInstruction *type_value = instruction->type_value->child;
+ if (type_is_invalid(type_value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ZigType *expr_type = ir_resolve_type(ira, type_value);
+ if (type_is_invalid(expr_type))
+ return ira->codegen->invalid_instruction;
+
+ // Only allow float types, and vectors of floats.
+ ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
+ if (float_type->id != ZigTypeIdFloat) {
+ ir_add_error(ira, type_value,
+ buf_sprintf("expected float or vector of float type, found '%s'", buf_ptr(&float_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *op1 = instruction->op1->child;
+ if (type_is_invalid(op1->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, expr_type);
+ if (type_is_invalid(casted_op1->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *op2 = instruction->op2->child;
+ if (type_is_invalid(op2->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, expr_type);
+ if (type_is_invalid(casted_op2->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *op3 = instruction->op3->child;
+ if (type_is_invalid(op3->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *casted_op3 = ir_implicit_cast(ira, op3, expr_type);
+ if (type_is_invalid(casted_op3->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (instr_is_comptime(casted_op1) &&
+ instr_is_comptime(casted_op2) &&
+ instr_is_comptime(casted_op3)) {
+ ConstExprValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad);
+ if (!op1_const)
+ return ira->codegen->invalid_instruction;
+ ConstExprValue *op2_const = ir_resolve_const(ira, casted_op2, UndefBad);
+ if (!op2_const)
+ return ira->codegen->invalid_instruction;
+ ConstExprValue *op3_const = ir_resolve_const(ira, casted_op3, UndefBad);
+ if (!op3_const)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
+ ConstExprValue *out_val = &result->value;
+
+ if (expr_type->id == ZigTypeIdVector) {
+ expand_undef_array(ira->codegen, op1_const);
+ expand_undef_array(ira->codegen, op2_const);
+ expand_undef_array(ira->codegen, op3_const);
+ out_val->special = ConstValSpecialUndef;
+ expand_undef_array(ira->codegen, out_val);
+ size_t len = expr_type->data.vector.len;
+ for (size_t i = 0; i < len; i += 1) {
+ ConstExprValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];
+ ConstExprValue *float_operand_op2 = &op2_const->data.x_array.data.s_none.elements[i];
+ ConstExprValue *float_operand_op3 = &op3_const->data.x_array.data.s_none.elements[i];
+ ConstExprValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
+ assert(float_operand_op1->type == float_type);
+ assert(float_operand_op2->type == float_type);
+ assert(float_operand_op3->type == float_type);
+ assert(float_out_val->type == float_type);
+ ir_eval_mul_add(ira, instruction, float_type,
+ op1_const, op2_const, op3_const, float_out_val);
+ float_out_val->type = float_type;
+ }
+ out_val->type = expr_type;
+ out_val->special = ConstValSpecialStatic;
+ } else {
+ ir_eval_mul_add(ira, instruction, float_type, op1_const, op2_const, op3_const, out_val);
+ }
+ return result;
+ }
+
+ IrInstruction *result = ir_build_mul_add(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node,
+ type_value, casted_op1, casted_op2, casted_op3);
+ result->value.type = expr_type;
+ return result;
+}
+
static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
@@ -23596,6 +23764,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
case IrInstructionIdSqrt:
return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdMulAdd:
+ return ir_analyze_instruction_mul_add(ira, (IrInstructionMulAdd *)instruction);
case IrInstructionIdIntToErr:
return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
case IrInstructionIdErrToInt:
@@ -23835,6 +24005,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCoroPromise:
case IrInstructionIdPromiseResultType:
case IrInstructionIdSqrt:
+ case IrInstructionIdMulAdd:
case IrInstructionIdAtomicLoad:
case IrInstructionIdIntCast:
case IrInstructionIdFloatCast:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index bf9ced89c5..e205c8e067 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1439,6 +1439,22 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_mul_add(IrPrint *irp, IrInstructionMulAdd *instruction) {
+ fprintf(irp->f, "@mulAdd(");
+ if (instruction->type_value != nullptr) {
+ ir_print_other_instruction(irp, instruction->type_value);
+ } else {
+ fprintf(irp->f, "null");
+ }
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->op1);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->op2);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->op3);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
ZigVar *var = decl_var_instruction->var;
const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
@@ -1905,6 +1921,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdSqrt:
ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
break;
+ case IrInstructionIdMulAdd:
+ ir_print_mul_add(irp, (IrInstructionMulAdd *)instruction);
+ break;
case IrInstructionIdAtomicLoad:
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
break;
diff --git a/test/stage1/behavior/muladd.zig b/test/stage1/behavior/muladd.zig
new file mode 100644
index 0000000000..143e6a93e4
--- /dev/null
+++ b/test/stage1/behavior/muladd.zig
@@ -0,0 +1,34 @@
+const expect = @import("std").testing.expect;
+
+test "@mulAdd" {
+ comptime testMulAdd();
+ testMulAdd();
+}
+
+fn testMulAdd() void {
+ {
+ var a: f16 = 5.5;
+ var b: f16 = 2.5;
+ var c: f16 = 6.25;
+ expect(@mulAdd(f16, a, b, c) == 20);
+ }
+ {
+ var a: f32 = 5.5;
+ var b: f32 = 2.5;
+ var c: f32 = 6.25;
+ expect(@mulAdd(f32, a, b, c) == 20);
+ }
+ {
+ var a: f64 = 5.5;
+ var b: f64 = 2.5;
+ var c: f64 = 6.25;
+ expect(@mulAdd(f64, a, b, c) == 20);
+ }
+ // Awaits implementation in libm.zig
+ //{
+ // var a: f16 = 5.5;
+ // var b: f128 = 2.5;
+ // var c: f128 = 6.25;
+ // expect(@mulAdd(f128, a, b, c) == 20);
+ //}
+}
\ No newline at end of file
--
cgit v1.2.3
From b588a803bf4493d2fd1892fe172b9ce8cfb0ca30 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 19 Jun 2019 14:35:59 -0400
Subject: fix comptime modification of const struct field
---
src/all_types.hpp | 3 +++
src/analyze.cpp | 2 +-
src/codegen.cpp | 2 +-
src/ir.cpp | 43 +++++++++++++++++++++++++++----------------
test/stage1/behavior.zig | 2 +-
test/stage1/behavior/eval.zig | 16 ++++++++--------
6 files changed, 41 insertions(+), 27 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 01f084218d..efb74e5ec3 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -334,6 +334,9 @@ struct ConstExprValue {
RuntimeHintPtr rh_ptr;
RuntimeHintSlice rh_slice;
} data;
+
+ ConstExprValue(const ConstExprValue &other) = delete; // plz zero initialize with {}
+ ConstExprValue& operator= (const ConstExprValue &other) = delete; // use copy_const_val
};
enum ReturnKnowledge {
diff --git a/src/analyze.cpp b/src/analyze.cpp
index b39b1e35ca..d048dd9770 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -4711,7 +4711,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
auto entry = g->string_literals_table.maybe_get(str);
if (entry != nullptr) {
- *const_val = *entry->value;
+ memcpy(const_val, entry->value, sizeof(ConstExprValue));
return;
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index dc2a4f55df..8f3a8df451 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -6676,7 +6676,7 @@ static void do_code_gen(CodeGen *g) {
zig_panic("TODO debug info for var with ptr casted value");
}
ZigType *var_type = g->builtin_types.entry_f128;
- ConstExprValue coerced_value;
+ ConstExprValue coerced_value = {};
coerced_value.special = ConstValSpecialStatic;
coerced_value.type = var_type;
coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
diff --git a/src/ir.cpp b/src/ir.cpp
index 83199fc0cc..3d125da1a1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -10624,13 +10624,16 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
ConstGlobalRefs *global_refs = dest->global_refs;
- assert(!same_global_refs || src->global_refs != nullptr);
- *dest = *src;
+ memcpy(dest, src, sizeof(ConstExprValue));
if (!same_global_refs) {
dest->global_refs = global_refs;
+ if (src->special == ConstValSpecialUndef)
+ return;
if (dest->type->id == ZigTypeIdStruct) {
- dest->data.x_struct.fields = allocate_nonzero(dest->type->data.structure.src_field_count);
- memcpy(dest->data.x_struct.fields, src->data.x_struct.fields, sizeof(ConstExprValue) * dest->type->data.structure.src_field_count);
+ dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count);
+ for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
+ copy_const_val(&dest->data.x_struct.fields[i], &src->data.x_struct.fields[i], false);
+ }
}
}
}
@@ -13579,7 +13582,7 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in
}
} else {
float_div_trunc(out_val, op1_val, op2_val);
- ConstExprValue remainder;
+ ConstExprValue remainder = {};
float_rem(&remainder, op1_val, op2_val);
if (float_cmp_zero(&remainder) != CmpEQ) {
return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
@@ -13954,8 +13957,8 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
// have a remainder function ambiguity problem
ok = true;
} else {
- ConstExprValue rem_result;
- ConstExprValue mod_result;
+ ConstExprValue rem_result = {};
+ ConstExprValue mod_result = {};
float_rem(&rem_result, op1_val, op2_val);
float_mod(&mod_result, op1_val, op2_val);
ok = float_cmp(&rem_result, &mod_result) == CmpEQ;
@@ -14178,10 +14181,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
size_t next_index = 0;
for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
- out_array_val->data.x_array.data.s_none.elements[next_index] = op1_array_val->data.x_array.data.s_none.elements[i];
+ copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
+ &op1_array_val->data.x_array.data.s_none.elements[i], true);
}
for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
- out_array_val->data.x_array.data.s_none.elements[next_index] = op2_array_val->data.x_array.data.s_none.elements[i];
+ copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
+ &op2_array_val->data.x_array.data.s_none.elements[i], true);
}
if (next_index < new_len) {
ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];
@@ -14242,7 +14247,8 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
uint64_t i = 0;
for (uint64_t x = 0; x < mult_amt; x += 1) {
for (uint64_t y = 0; y < old_array_len; y += 1) {
- out_val->data.x_array.data.s_none.elements[i] = array_val->data.x_array.data.s_none.elements[y];
+ copy_const_val(&out_val->data.x_array.data.s_none.elements[i],
+ &array_val->data.x_array.data.s_none.elements[y], true);
i += 1;
}
}
@@ -14382,7 +14388,12 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
if (instr_is_comptime(var_ptr) && var_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
init_val = const_ptr_pointee(ira, ira->codegen, &var_ptr->value, decl_var_instruction->base.source_node);
if (is_comptime_var) {
- var->const_value = init_val;
+ if (var->gen_is_const) {
+ var->const_value = init_val;
+ } else {
+ var->const_value = create_const_vals(1);
+ copy_const_val(var->const_value, init_val, false);
+ }
}
}
@@ -15291,7 +15302,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
arg_val = create_const_runtime(casted_arg->value.type);
}
if (arg_part_of_generic_id) {
- generic_id->params[generic_id->param_count] = *arg_val;
+ copy_const_val(&generic_id->params[generic_id->param_count], arg_val, true);
generic_id->param_count += 1;
}
@@ -15476,7 +15487,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
// * "string literal used as comptime slice is memoized"
// * "comptime modification of const struct field" - except modified to avoid
// ConstPtrMutComptimeVar, thus defeating the logic below.
- bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
+ bool same_global_refs = ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
copy_const_val(dest_val, &value->value, same_global_refs);
if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
@@ -15877,7 +15888,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
- const_instruction->base.value = *align_result;
+ copy_const_val(&const_instruction->base.value, align_result, true);
uint32_t align_bytes = 0;
ir_resolve_align(ira, &const_instruction->base, &align_bytes);
@@ -21667,7 +21678,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
ConstExprValue *byte_val = &casted_byte->value;
for (size_t i = start; i < end; i += 1) {
- dest_elements[i] = *byte_val;
+ copy_const_val(&dest_elements[i], byte_val, true);
}
return ir_const_void(ira, &instruction->base);
@@ -21835,7 +21846,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
// TODO check for noalias violations - this should be generalized to work for any function
for (size_t i = 0; i < count; i += 1) {
- dest_elements[dest_start + i] = src_elements[src_start + i];
+ copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);
}
return ir_const_void(ira, &instruction->base);
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index ccbec6849a..77fc482ccc 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -48,7 +48,7 @@ comptime {
_ = @import("behavior/enum.zig"); // TODO
_ = @import("behavior/enum_with_members.zig");
_ = @import("behavior/error.zig"); // TODO
- _ = @import("behavior/eval.zig"); // TODO
+ _ = @import("behavior/eval.zig");
_ = @import("behavior/field_parent_ptr.zig");
_ = @import("behavior/fn.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig
index 62cedbc76f..97d3a269cc 100644
--- a/test/stage1/behavior/eval.zig
+++ b/test/stage1/behavior/eval.zig
@@ -583,14 +583,14 @@ pub const Info = struct {
pub const diamond_info = Info{ .version = 0 };
-//test "comptime modification of const struct field" {
-// comptime {
-// var res = diamond_info;
-// res.version = 1;
-// expect(diamond_info.version == 0);
-// expect(res.version == 1);
-// }
-//}
+test "comptime modification of const struct field" {
+ comptime {
+ var res = diamond_info;
+ res.version = 1;
+ expect(diamond_info.version == 0);
+ expect(res.version == 1);
+ }
+}
test "pointer to type" {
comptime {
--
cgit v1.2.3
From 974db231a08731f642dbf72d716f669fed2bd2ab Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 19 Jun 2019 16:16:47 -0400
Subject: fix extraneous nested union field instruction
---
src/codegen.cpp | 7 ++++++-
test/stage1/behavior.zig | 2 +-
test/stage1/behavior/enum.zig | 32 ++++++++++++++++----------------
3 files changed, 23 insertions(+), 18 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 8f3a8df451..bd3bae66fc 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3853,6 +3853,9 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionUnionFieldPtr *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
ZigType *union_ptr_type = instruction->union_ptr->value.type;
assert(union_ptr_type->id == ZigTypeIdPointer);
ZigType *union_type = union_ptr_type->data.pointer.child_type;
@@ -4077,6 +4080,9 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionOptionalUnwrapPtr *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
ZigType *ptr_type = instruction->base_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *maybe_type = ptr_type->data.pointer.child_type;
@@ -5750,7 +5756,6 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
assert(executable->basic_block_list.length > 0);
for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
- //assert(current_block->ref_count > 0);
assert(current_block->llvm_block);
LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 5ad6b94f3f..0e93290cc4 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -45,7 +45,7 @@ comptime {
//_ = @import("behavior/coroutine_await_struct.zig");
//_ = @import("behavior/coroutines.zig");
_ = @import("behavior/defer.zig");
- _ = @import("behavior/enum.zig"); // TODO
+ _ = @import("behavior/enum.zig");
_ = @import("behavior/enum_with_members.zig");
_ = @import("behavior/error.zig"); // TODO
_ = @import("behavior/eval.zig");
diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig
index e06a075974..51f4f0e196 100644
--- a/test/stage1/behavior/enum.zig
+++ b/test/stage1/behavior/enum.zig
@@ -1,22 +1,22 @@
const expect = @import("std").testing.expect;
const mem = @import("std").mem;
-//test "enum type" {
-// const foo1 = Foo{ .One = 13 };
-// const foo2 = Foo{
-// .Two = Point{
-// .x = 1234,
-// .y = 5678,
-// },
-// };
-// const bar = Bar.B;
-//
-// expect(bar == Bar.B);
-// expect(@memberCount(Foo) == 3);
-// expect(@memberCount(Bar) == 4);
-// expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
-// expect(@sizeOf(Bar) == 1);
-//}
+test "enum type" {
+ const foo1 = Foo{ .One = 13 };
+ const foo2 = Foo{
+ .Two = Point{
+ .x = 1234,
+ .y = 5678,
+ },
+ };
+ const bar = Bar.B;
+
+ expect(bar == Bar.B);
+ expect(@memberCount(Foo) == 3);
+ expect(@memberCount(Bar) == 4);
+ expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
+ expect(@sizeOf(Bar) == 1);
+}
test "enum as return value" {
switch (returnAnInt(13)) {
--
cgit v1.2.3
From 96931228af745b8e69c138b3b83893dafa166cfe Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 19 Jun 2019 16:29:46 -0400
Subject: fix comptime test error for empty error set
---
src/all_types.hpp | 1 +
src/codegen.cpp | 6 ++++++
src/ir.cpp | 26 ++++++++++++++++++++------
test/stage1/behavior/error.zig | 16 ++++++++--------
4 files changed, 35 insertions(+), 14 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index efb74e5ec3..e376c4d4e8 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3085,6 +3085,7 @@ struct IrInstructionAlignOf {
struct IrInstructionTestErrSrc {
IrInstruction base;
+ bool resolve_err_set;
IrInstruction *base_ptr;
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index bd3bae66fc..05bdf92555 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4913,6 +4913,9 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
IrInstructionUnwrapErrCode *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
ZigType *ptr_type = instruction->err_union_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *err_union_type = ptr_type->data.pointer.child_type;
@@ -4930,6 +4933,9 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
IrInstructionUnwrapErrPayload *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
bool want_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base) &&
g->errors_by_index.length > 1;
if (!want_safety && !type_has_bits(instruction->base.value.type))
diff --git a/src/ir.cpp b/src/ir.cpp
index 6dfaa168ec..6de4202c5f 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -2446,10 +2446,11 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
}
static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *base_ptr)
+ IrInstruction *base_ptr, bool resolve_err_set)
{
IrInstructionTestErrSrc *instruction = ir_build_instruction(irb, scope, source_node);
instruction->base_ptr = base_ptr;
+ instruction->resolve_err_set = resolve_err_set;
ir_ref_instruction(base_ptr, irb->current_basic_block);
@@ -3593,7 +3594,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,
return_value);
- IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr, false);
bool should_inline = ir_should_inline(irb->exec, scope);
IrInstruction *is_comptime;
@@ -3639,7 +3640,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr);
+ IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true);
IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
@@ -5987,7 +5988,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
LValPtr, nullptr);
if (err_val_ptr == irb->codegen->invalid_instruction)
return err_val_ptr;
- IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, true);
IrBasicBlock *after_cond_block = irb->current_basic_block;
IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
IrInstruction *cond_br_inst;
@@ -6771,7 +6772,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
return err_val_ptr;
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
- IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr);
+ IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true);
IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
@@ -7381,7 +7382,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr);
+ IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true);
IrInstruction *is_comptime;
if (ir_should_inline(irb->exec, parent_scope)) {
@@ -22512,6 +22513,19 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
}
}
+ if (instruction->resolve_err_set) {
+ ZigType *err_set_type = type_entry->data.error_union.err_set_type;
+ if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
+ return ira->codegen->invalid_instruction;
+ }
+ if (!type_is_global_error_set(err_set_type) &&
+ err_set_type->data.error_set.err_count == 0)
+ {
+ assert(err_set_type->data.error_set.infer_fn == nullptr);
+ return ir_const_bool(ira, &instruction->base, false);
+ }
+ }
+
return ir_build_test_err_gen(ira, &instruction->base, value);
} else if (type_entry->id == ZigTypeIdErrorSet) {
return ir_const_bool(ira, &instruction->base, true);
diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig
index 1f8f8b36e4..861c500751 100644
--- a/test/stage1/behavior/error.zig
+++ b/test/stage1/behavior/error.zig
@@ -130,10 +130,10 @@ fn testExplicitErrorSetCast(set1: Set1) void {
expect(y == error.A);
}
-//test "comptime test error for empty error set" {
-// testComptimeTestErrorEmptySet(1234);
-// comptime testComptimeTestErrorEmptySet(1234);
-//}
+test "comptime test error for empty error set" {
+ testComptimeTestErrorEmptySet(1234);
+ comptime testComptimeTestErrorEmptySet(1234);
+}
const EmptyErrorSet = error{};
@@ -204,10 +204,10 @@ fn foo2(f: fn () anyerror!void) void {
fn bar2() (error{}!void) {}
-//test "error: Zero sized error set returned with value payload crash" {
-// _ = foo3(0) catch {};
-// _ = comptime foo3(0) catch {};
-//}
+test "error: Zero sized error set returned with value payload crash" {
+ _ = foo3(0) catch {};
+ _ = comptime foo3(0) catch {};
+}
const Error = error{};
fn foo3(b: usize) Error!usize {
--
cgit v1.2.3
From 4ffab5b85f03f63a7e724698482f8497cacc7212 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 19 Jun 2019 18:47:02 -0400
Subject: fix optional pointer to size zero struct
---
src/codegen.cpp | 15 ++++++++++++---
src/ir.cpp | 15 ++++++++++-----
test/stage1/behavior.zig | 4 ++--
test/stage1/behavior/optional.zig | 10 +++++-----
test/stage1/behavior/ptrcast.zig | 14 +++++++-------
5 files changed, 36 insertions(+), 22 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 05bdf92555..b55b8a1094 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4983,7 +4983,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
}
}
-static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
+static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
ZigType *wanted_type = instruction->base.value.type;
assert(wanted_type->id == ZigTypeIdOptional);
@@ -4991,11 +4991,20 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
ZigType *child_type = wanted_type->data.maybe.child_type;
if (!type_has_bits(child_type)) {
- return LLVMConstInt(LLVMInt1Type(), 1, false);
+ LLVMValueRef result = LLVMConstAllOnes(LLVMInt1Type());
+ if (instruction->result_loc != nullptr) {
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+ gen_store_untyped(g, result, result_loc, 0, false);
+ }
+ return result;
}
LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
if (!handle_is_ptr(wanted_type)) {
+ if (instruction->result_loc != nullptr) {
+ LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
+ gen_store_untyped(g, payload_val, result_loc, 0, false);
+ }
return payload_val;
}
@@ -5666,7 +5675,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdUnwrapErrPayload:
return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);
case IrInstructionIdOptionalWrap:
- return ir_render_maybe_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);
+ return ir_render_optional_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);
case IrInstructionIdErrWrapCode:
return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
case IrInstructionIdErrWrapPayload:
diff --git a/src/ir.cpp b/src/ir.cpp
index 356a1a8cc8..0a920c0974 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1826,7 +1826,7 @@ static IrInstruction *ir_build_optional_wrap(IrAnalyze *ira, IrInstruction *sour
instruction->result_loc = result_loc;
ir_ref_instruction(operand, ira->new_irb.current_basic_block);
- ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -11277,10 +11277,15 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
return &const_instruction->base;
}
- if (result_loc == nullptr) result_loc = no_result_loc();
- IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
- if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
- return result_loc_inst;
+ if (result_loc == nullptr && handle_is_ptr(wanted_type)) {
+ result_loc = no_result_loc();
+ }
+ IrInstruction *result_loc_inst = nullptr;
+ if (result_loc != nullptr) {
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
+ if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
+ return result_loc_inst;
+ }
}
IrInstruction *result = ir_build_optional_wrap(ira, source_instr, wanted_type, value, result_loc_inst);
result->value.data.rh_maybe = RuntimeHintOptionalNonNull;
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 5824f9380f..0387f3c045 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -66,10 +66,10 @@ comptime {
_ = @import("behavior/namespace_depends_on_compile_var.zig");
_ = @import("behavior/new_stack_call.zig");
_ = @import("behavior/null.zig");
- _ = @import("behavior/optional.zig"); // TODO
+ _ = @import("behavior/optional.zig");
_ = @import("behavior/pointers.zig");
_ = @import("behavior/popcount.zig");
- _ = @import("behavior/ptrcast.zig"); // TODO
+ _ = @import("behavior/ptrcast.zig");
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/reflection.zig");
diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig
index 09260c4778..b33e250383 100644
--- a/test/stage1/behavior/optional.zig
+++ b/test/stage1/behavior/optional.zig
@@ -2,11 +2,11 @@ const expect = @import("std").testing.expect;
pub const EmptyStruct = struct {};
-//test "optional pointer to size zero struct" {
-// var e = EmptyStruct{};
-// var o: ?*EmptyStruct = &e;
-// expect(o != null);
-//}
+test "optional pointer to size zero struct" {
+ var e = EmptyStruct{};
+ var o: ?*EmptyStruct = &e;
+ expect(o != null);
+}
test "equality compare nullable pointers" {
testNullPtrsEql();
diff --git a/test/stage1/behavior/ptrcast.zig b/test/stage1/behavior/ptrcast.zig
index 004ae4dd83..bf92888214 100644
--- a/test/stage1/behavior/ptrcast.zig
+++ b/test/stage1/behavior/ptrcast.zig
@@ -59,10 +59,10 @@ test "comptime ptrcast keeps larger alignment" {
}
}
-//test "implicit optional pointer to optional c_void pointer" {
-// var buf: [4]u8 = "aoeu";
-// var x: ?[*]u8 = &buf;
-// var y: ?*c_void = x;
-// var z = @ptrCast(*[4]u8, y);
-// expect(std.mem.eql(u8, z, "aoeu"));
-//}
+test "implicit optional pointer to optional c_void pointer" {
+ var buf: [4]u8 = "aoeu";
+ var x: ?[*]u8 = &buf;
+ var y: ?*c_void = x;
+ var z = @ptrCast(*[4]u8, y);
+ expect(std.mem.eql(u8, z, "aoeu"));
+}
--
cgit v1.2.3
From 78eeb6e9aea9c280513faaa83f9df959b7ac6f59 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 19 Jun 2019 22:29:39 -0400
Subject: fix double getelementptr of runtime global
---
src/codegen.cpp | 3 +
src/ir.cpp | 186 +++++++++++++++-------------------------
test/stage1/behavior/struct.zig | 12 +--
3 files changed, 76 insertions(+), 125 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 6830007f32..5cb65b38f3 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3832,6 +3832,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionStructFieldPtr *instruction)
{
+ if (instruction->base.value.special != ConstValSpecialRuntime)
+ return nullptr;
+
LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
// not necessarily a pointer. could be ZigTypeIdStruct
ZigType *struct_ptr_type = instruction->struct_ptr->value.type;
diff --git a/src/ir.cpp b/src/ir.cpp
index b2ff8f5896..9ac83443ab 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -187,9 +187,9 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *dest_type);
static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
- ResultLoc *result_loc, ZigType *value_type, IrInstruction *value);
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool non_null_comptime);
static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
- ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime);
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *base_ptr, bool safety_check_on, bool initializing);
static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
@@ -10844,7 +10844,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
}
if (result_loc == nullptr) result_loc = no_result_loc();
- IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -11282,7 +11282,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
}
IrInstruction *result_loc_inst = nullptr;
if (result_loc != nullptr) {
- result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -11325,7 +11325,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
IrInstruction *result_loc_inst;
if (handle_is_ptr(wanted_type)) {
if (result_loc == nullptr) result_loc = no_result_loc();
- result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -11410,7 +11410,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
IrInstruction *result_loc_inst;
if (handle_is_ptr(wanted_type)) {
if (result_loc == nullptr) result_loc = no_result_loc();
- result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
+ result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -11483,7 +11483,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
IrInstruction *result_loc;
if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
- result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true);
+ result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true, false);
} else {
result_loc = nullptr;
}
@@ -11527,7 +11527,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
if (result_loc == nullptr) result_loc = no_result_loc();
- IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true);
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -12180,7 +12180,7 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
result->value.type = array_type;
return result;
}
- IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true);
+ IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -12761,7 +12761,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
IrInstruction *result_loc_inst;
if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
if (result_loc == nullptr) result_loc = no_result_loc();
- result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true);
+ result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, false);
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
@@ -14910,7 +14910,7 @@ static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) {
// when calling this function, at the callsite must check for result type noreturn and propagate it up
static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
- ResultLoc *result_loc, ZigType *value_type, IrInstruction *value)
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool non_null_comptime)
{
Error err;
if (result_loc->resolved_loc != nullptr) {
@@ -14984,9 +14984,11 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
return result_loc->resolved_loc;
}
case ResultLocIdReturn: {
- bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
- if (is_comptime)
- return nullptr;
+ if (!non_null_comptime) {
+ bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
+ if (is_comptime)
+ return nullptr;
+ }
if (!type_has_bits(ira->explicit_return_type) || !handle_is_ptr(ira->explicit_return_type))
return nullptr;
@@ -15005,6 +15007,10 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
return ira->codegen->invalid_instruction;
peer_parent->skipped = is_comptime;
if (peer_parent->skipped) {
+ if (non_null_comptime) {
+ return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
+ value_type, value, false, non_null_comptime);
+ }
return nullptr;
}
@@ -15016,7 +15022,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
}
IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
- peer_parent->resolved_type, nullptr, false);
+ peer_parent->resolved_type, nullptr, false, non_null_comptime);
if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
parent_result_loc->value.type->id == ZigTypeIdUnreachable)
{
@@ -15066,7 +15072,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
}
IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
- dest_type, bitcasted_value, false);
+ dest_type, bitcasted_value, false, non_null_comptime);
if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
parent_result_loc->value.type->id == ZigTypeIdUnreachable)
{
@@ -15094,10 +15100,11 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
}
static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
- ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime)
+ ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,
+ bool non_null_comptime)
{
IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
- value);
+ value, non_null_comptime);
if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type)))
return result_loc;
@@ -15144,23 +15151,16 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
if (type_is_invalid(implicit_elem_type))
return ira->codegen->invalid_instruction;
- ResultLoc *old_result_loc = instruction->result_loc;
- for (;;) {
- IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, old_result_loc,
- implicit_elem_type, nullptr, false);
- if (result_loc != nullptr)
- return result_loc;
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ implicit_elem_type, nullptr, false, true);
+ if (result_loc != nullptr)
+ return result_loc;
- if (instruction->result_loc->id == ResultLocIdPeer) {
- old_result_loc = reinterpret_cast(instruction->result_loc)->parent->parent;
- continue;
- }
- IrInstruction *result = ir_const(ira, &instruction->base, implicit_elem_type);
- result->value.special = ConstValSpecialUndef;
- IrInstruction *ptr = ir_get_ref(ira, &instruction->base, result, false, false);
- ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
- return ptr;
- }
+ IrInstruction *result = ir_const(ira, &instruction->base, implicit_elem_type);
+ result->value.special = ConstValSpecialUndef;
+ IrInstruction *ptr = ir_get_ref(ira, &instruction->base, result, false, false);
+ ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
+ return ptr;
}
static void ir_reset_result(ResultLoc *result_loc) {
@@ -15500,7 +15500,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
// * "string literal used as comptime slice is memoized"
// * "comptime modification of const struct field" - except modified to avoid
// ConstPtrMutComptimeVar, thus defeating the logic below.
- bool same_global_refs = ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
+ bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
copy_const_val(dest_val, &value->value, same_global_refs);
if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
@@ -15986,7 +15986,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
IrInstruction *result_loc;
if (handle_is_ptr(impl_fn_type_id->return_type)) {
result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
- impl_fn_type_id->return_type, nullptr, true);
+ impl_fn_type_id->return_type, nullptr, true, false);
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
return result_loc;
}
@@ -16106,7 +16106,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
IrInstruction *result_loc;
if (handle_is_ptr(return_type)) {
result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
- return_type, nullptr, true);
+ return_type, nullptr, true, false);
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
return result_loc;
}
@@ -16198,7 +16198,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
if (dst_size <= src_size) {
if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
- copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
+ copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
return ErrorNone;
}
Buf buf = BUF_INIT;
@@ -16600,7 +16600,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
// In case resolving the parent activates a suspend, do it now
IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
- peer_parent->resolved_type, nullptr, false);
+ peer_parent->resolved_type, nullptr, false, false);
if (parent_result_loc != nullptr &&
(type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))
{
@@ -17246,11 +17246,10 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
field_val->special = ConstValSpecialUndef;
field_val->type = struct_type->data.structure.fields[i].type_entry;
ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdStruct;
- parent->data.p_struct.struct_val = struct_val;
- parent->data.p_struct.field_index = i;
- }
+ assert(parent != nullptr);
+ parent->id = ConstParentIdStruct;
+ parent->data.p_struct.struct_val = struct_val;
+ parent->data.p_struct.field_index = i;
}
}
IrInstruction *result;
@@ -17264,7 +17263,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
}
ConstExprValue *const_val = &result->value;
const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
- const_val->data.x_ptr.mut = struct_ptr->value.data.x_ptr.mut;
+ const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
return result;
@@ -17414,6 +17413,11 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
link_lib->symbols.append(symbol_name);
}
+static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
+ emit_error_notes_for_ref_stack(ira->codegen, msg);
+ return ira->codegen->invalid_instruction;
+}
static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node);
@@ -17428,6 +17432,9 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
{
TldVar *tld_var = (TldVar *)tld;
ZigVar *var = tld_var->var;
+ if (var == nullptr) {
+ return ir_error_dependency_loop(ira, source_instruction);
+ }
if (tld_var->extern_lib_name != nullptr) {
add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node);
}
@@ -17443,23 +17450,13 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
if (type_is_invalid(fn_entry->type_entry))
return ira->codegen->invalid_instruction;
- // TODO instead of allocating this every time, put it in the tld value and we can reference
- // the same one every time
- ConstExprValue *const_val = create_const_vals(1);
- const_val->special = ConstValSpecialStatic;
- const_val->type = fn_entry->type_entry;
- const_val->data.x_ptr.data.fn.fn_entry = fn_entry;
- const_val->data.x_ptr.special = ConstPtrSpecialFunction;
- const_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
-
if (tld_fn->extern_lib_name != nullptr) {
add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node);
}
- bool ptr_is_const = true;
- bool ptr_is_volatile = false;
- return ir_get_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
+ IrInstruction *fn_inst = ir_create_const_fn(&ira->new_irb, source_instruction->scope,
+ source_instruction->source_node, fn_entry);
+ return ir_get_ref(ira, source_instruction, fn_inst, true, false);
}
}
zig_unreachable();
@@ -19673,12 +19670,6 @@ static IrInstruction *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
return ir_const_unsigned(ira, &instruction->base, bit_offset);
}
-static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
- ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
- emit_error_notes_for_ref_stack(ira->codegen, msg);
- return ira->codegen->invalid_instruction;
-}
-
static void ensure_field_index(ZigType *type, const char *field_name, size_t index) {
Buf *field_name_buf;
@@ -21088,7 +21079,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
IrInstruction *result_loc;
if (handle_is_ptr(result_type)) {
result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
- result_type, nullptr, true);
+ result_type, nullptr, true, false);
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
return result_loc;
}
@@ -21345,7 +21336,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
}
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
- dest_slice_type, nullptr, true);
+ dest_slice_type, nullptr, true, false);
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
return result_loc;
}
@@ -21422,7 +21413,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
}
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
- dest_slice_type, nullptr, true);
+ dest_slice_type, nullptr, true, false);
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
return result_loc;
}
@@ -22164,7 +22155,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
}
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
- return_type, nullptr, true);
+ return_type, nullptr, true, false);
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
return result_loc;
}
@@ -23729,58 +23720,15 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
IrInstructionDeclRef *instruction)
{
- Tld *tld = instruction->tld;
- LVal lval = instruction->lval;
-
- resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node);
- if (tld->resolution == TldResolutionInvalid)
+ IrInstruction *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base, instruction->tld);
+ if (type_is_invalid(ref_instruction->value.type))
return ira->codegen->invalid_instruction;
- switch (tld->id) {
- case TldIdContainer:
- case TldIdCompTime:
- zig_unreachable();
- case TldIdVar: {
- TldVar *tld_var = (TldVar *)tld;
- ZigVar *var = tld_var->var;
-
- if (var == nullptr) {
- return ir_error_dependency_loop(ira, &instruction->base);
- }
-
- IrInstruction *var_ptr = ir_get_var_ptr(ira, &instruction->base, var);
- if (type_is_invalid(var_ptr->value.type))
- return ira->codegen->invalid_instruction;
-
- if (tld_var->extern_lib_name != nullptr) {
- add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, instruction->base.source_node);
- }
-
- if (lval == LValPtr) {
- return var_ptr;
- } else {
- return ir_get_deref(ira, &instruction->base, var_ptr, nullptr);
- }
- }
- case TldIdFn: {
- TldFn *tld_fn = (TldFn *)tld;
- ZigFn *fn_entry = tld_fn->fn_entry;
- ir_assert(fn_entry->type_entry, &instruction->base);
-
- if (tld_fn->extern_lib_name != nullptr) {
- add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, instruction->base.source_node);
- }
-
- IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, fn_entry);
- if (lval == LValPtr) {
- return ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
- } else {
- return ref_instruction;
- }
- }
+ if (instruction->lval == LValPtr) {
+ return ref_instruction;
+ } else {
+ return ir_get_deref(ira, &instruction->base, ref_instruction, nullptr);
}
- zig_unreachable();
}
static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) {
@@ -24655,7 +24603,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
bool was_written = instruction->result_loc->written;
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
- value->value.type, value, false);
+ value->value.type, value, false, false);
if (result_loc != nullptr) {
if (type_is_invalid(result_loc->value.type))
return ira->codegen->invalid_instruction;
@@ -24684,7 +24632,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst
return operand;
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base,
- &instruction->result_loc_bit_cast->base, operand->value.type, operand, false);
+ &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false);
if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
return result_loc;
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index a08dec5359..ccdff3503e 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -522,12 +522,12 @@ const S0 = struct {
}
};
-//var g_foo: S0 = S0.init();
-//
-//test "access to global struct fields" {
-// g_foo.bar.value = 42;
-// expect(g_foo.bar.value == 42);
-//}
+var g_foo: S0 = S0.init();
+
+test "access to global struct fields" {
+ g_foo.bar.value = 42;
+ expect(g_foo.bar.value == 42);
+}
//test "packed struct with fp fields" {
// const S = packed struct {
--
cgit v1.2.3
From 237233b04bdbbb82a5ce881a074fdd4ca55fe58f Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 20 Jun 2019 18:15:27 -0400
Subject: fix coroutines
---
src/codegen.cpp | 2 +-
src/ir.cpp | 8 +++++++-
test/stage1/behavior.zig | 6 +++---
3 files changed, 11 insertions(+), 5 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 5cb65b38f3..79c92964f6 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3755,7 +3755,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
bool is_var_args = fn_type_id->is_var_args;
ZigList gen_param_values = {};
- LLVMValueRef result_loc = first_arg_ret ? ir_llvm_value(g, instruction->result_loc) : nullptr;
+ LLVMValueRef result_loc = (first_arg_ret || instruction->is_async) ? ir_llvm_value(g, instruction->result_loc) : nullptr;
if (first_arg_ret) {
gen_param_values.append(result_loc);
}
diff --git a/src/ir.cpp b/src/ir.cpp
index 4dbc20cf48..c3ed14770f 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15252,8 +15252,14 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
ZigType *promise_type = get_promise_type(ira->codegen, return_type);
ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
+ IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, no_result_loc(),
+ async_return_type, nullptr, true, true);
+ if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ return result_loc;
+ }
+
return ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
- casted_args, FnInlineAuto, true, async_allocator_inst, nullptr, nullptr,
+ casted_args, FnInlineAuto, true, async_allocator_inst, nullptr, result_loc,
async_return_type);
}
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 8fcd9b86b8..f477bb64ed 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -39,11 +39,11 @@ comptime {
_ = @import("behavior/bugs/828.zig");
_ = @import("behavior/bugs/920.zig");
_ = @import("behavior/byval_arg_var.zig");
- //_ = @import("behavior/cancel.zig");
+ _ = @import("behavior/cancel.zig");
_ = @import("behavior/cast.zig");
_ = @import("behavior/const_slice_child.zig");
- //_ = @import("behavior/coroutine_await_struct.zig");
- //_ = @import("behavior/coroutines.zig");
+ _ = @import("behavior/coroutine_await_struct.zig");
+ _ = @import("behavior/coroutines.zig");
_ = @import("behavior/defer.zig");
_ = @import("behavior/enum.zig");
_ = @import("behavior/enum_with_members.zig");
--
cgit v1.2.3
From 142e77abbb8a88c2c6473921d0c600faf3d34a62 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 21 Jun 2019 14:44:49 -0400
Subject: fix extern functions returning byval structs
---
src/codegen.cpp | 48 +++++++++++++++++++++++++----------------
test/stage1/behavior/struct.zig | 21 ++++++++++++++++++
2 files changed, 50 insertions(+), 19 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 79c92964f6..5b7169f312 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2394,24 +2394,31 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
- if (return_instruction->value == nullptr) {
- LLVMBuildRetVoid(g->builder);
- return nullptr;
- }
-
- ZigType *return_type = return_instruction->value->value.type;
-
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
+ if (return_instruction->value == nullptr) {
+ LLVMBuildRetVoid(g->builder);
+ return nullptr;
+ }
assert(g->cur_ret_ptr);
src_assert(return_instruction->value->value.special != ConstValSpecialRuntime,
return_instruction->base.source_node);
LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
+ ZigType *return_type = return_instruction->value->value.type;
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
LLVMBuildRetVoid(g->builder);
- } else if (handle_is_ptr(return_type)) {
- LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
- LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
- LLVMBuildRet(g->builder, by_val_value);
+ } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
+ handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
+ {
+ if (return_instruction->value == nullptr) {
+ LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, "");
+ LLVMBuildRet(g->builder, by_val_value);
+ } else {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
+ LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
+ LLVMBuildRet(g->builder, by_val_value);
+ }
+ } else if (return_instruction->value == nullptr) {
+ LLVMBuildRetVoid(g->builder);
} else {
LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
LLVMBuildRet(g->builder, value);
@@ -3755,7 +3762,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
bool is_var_args = fn_type_id->is_var_args;
ZigList gen_param_values = {};
- LLVMValueRef result_loc = (first_arg_ret || instruction->is_async) ? ir_llvm_value(g, instruction->result_loc) : nullptr;
+ LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
if (first_arg_ret) {
gen_param_values.append(result_loc);
}
@@ -6804,20 +6811,24 @@ static void do_code_gen(CodeGen *g) {
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
CallingConvention cc = fn_type_id->cc;
bool is_c_abi = cc == CallingConventionC;
+ bool want_sret = want_first_arg_sret(g, fn_type_id);
LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
g->cur_fn = fn_table_entry;
g->cur_fn_val = fn;
- ZigType *return_type = fn_type_id->return_type;
- if (handle_is_ptr(return_type)) {
+
+ build_all_basic_blocks(g, fn_table_entry);
+ clear_debug_source_node(g);
+
+ if (want_sret) {
g->cur_ret_ptr = LLVMGetParam(fn, 0);
+ } else if (handle_is_ptr(fn_type_id->return_type)) {
+ g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
+ // TODO add debug info variable for this
} else {
g->cur_ret_ptr = nullptr;
}
- build_all_basic_blocks(g, fn_table_entry);
- clear_debug_source_node(g);
-
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;
if (have_err_ret_trace_arg) {
@@ -6863,8 +6874,7 @@ static void do_code_gen(CodeGen *g) {
}
ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base);
-
- unsigned gen_i_init = want_first_arg_sret(g, fn_type_id) ? 1 : 0;
+ unsigned gen_i_init = want_sret ? 1 : 0;
// create debug variable declarations for variables and allocate all local variables
FnWalk fn_walk_var = {};
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index 0ebd0654d0..b86b171daf 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -578,3 +578,24 @@ test "default struct initialization fields" {
};
expectEqual(1239, x.a + x.b);
}
+
+test "extern fn returns struct by value" {
+ const S = struct {
+ fn entry() void {
+ var x = makeBar(10);
+ expectEqual(i32(10), x.handle);
+ }
+
+ const ExternBar = extern struct {
+ handle: i32,
+ };
+
+ extern fn makeBar(t: i32) ExternBar {
+ return ExternBar{
+ .handle = t,
+ };
+ }
+ };
+ S.entry();
+ comptime S.entry();
+}
--
cgit v1.2.3
From 71e014caecaa54fdd8a0516710d2d9597da41398 Mon Sep 17 00:00:00 2001
From: Shawn Landden
Date: Fri, 21 Jun 2019 16:18:59 -0500
Subject: stage1: add @sin @cos @exp @exp2 @ln @log2 @log10 @fabs @floor @ceil
@trunc @round
and expand @sqrt
This revealed that the accuracy of ln is not as good as the current algorithm in
musl and glibc, and should be ported again.
v2: actually include tests
v3: fix reversal of in and out arguments on f128M_sqrt()
add test for @sqrt on comptime_float
do not include @nearbyInt() until it works on all targets.
---
doc/langref.html.in | 85 +++++++++-
src/all_types.hpp | 26 ++-
src/analyze.cpp | 15 +-
src/codegen.cpp | 68 ++++----
src/ir.cpp | 355 ++++++++++++++++++++++++++++++++-------
src/ir.hpp | 1 +
src/ir_print.cpp | 11 +-
src/util.cpp | 1 +
std/special/c.zig | 44 +++--
test/stage1/behavior.zig | 1 +
test/stage1/behavior/floatop.zig | 243 +++++++++++++++++++++++++++
11 files changed, 719 insertions(+), 131 deletions(-)
create mode 100644 test/stage1/behavior/floatop.zig
(limited to 'src/codegen.cpp')
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 9b95946256..30fe9a3648 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -7354,10 +7354,91 @@ test "@setRuntimeSafety" {
{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}
Performs the square root of a floating point number. Uses a dedicated hardware instruction
- when available. Currently only supports f32 and f64 at runtime. f128 at runtime is TODO.
+ when available. Supports f16, f32, f64, and f128, as well as vectors.
+ {#header_close#}
+ {#header_open|@sin#}
+ {#syntax#}@sin(comptime T: type, value: T) T{#endsyntax#}
+
+ Sine trigometric function on a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@cos#}
+ {#syntax#}@cos(comptime T: type, value: T) T{#endsyntax#}
+
+ Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@exp#}
+ {#syntax#}@exp(comptime T: type, value: T) T{#endsyntax#}
+
+ Base-e exponential function on a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@exp2#}
+ {#syntax#}@exp2(comptime T: type, value: T) T{#endsyntax#}
+
+ Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@ln#}
+ {#syntax#}@ln(comptime T: type, value: T) T{#endsyntax#}
+
+ Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@log2#}
+ {#syntax#}@log2(comptime T: type, value: T) T{#endsyntax#}
+
+ Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@log10#}
+ {#syntax#}@log10(comptime T: type, value: T) T{#endsyntax#}
+
+ Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@fabs#}
+ {#syntax#}@fabs(comptime T: type, value: T) T{#endsyntax#}
+
+ Returns the absolute value of a floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@floor#}
+ {#syntax#}@floor(comptime T: type, value: T) T{#endsyntax#}
+
+ Returns the largest integral value not greater than the given floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@ceil#}
+ {#syntax#}@ceil(comptime T: type, value: T) T{#endsyntax#}
+
+ Returns the largest integral value not less than the given floating point number. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@trunc#}
+ {#syntax#}@trunc(comptime T: type, value: T) T{#endsyntax#}
+
+ Rounds the given floating point number to an integer, towards zero. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
+
+ {#header_close#}
+ {#header_open|@round#}
+ {#syntax#}@round(comptime T: type, value: T) T{#endsyntax#}
- This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
+ Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction
+ when available. Currently supports f32 and f64.
{#header_close#}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 83df71b95f..6595218bcf 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1434,6 +1434,19 @@ enum BuiltinFnId {
BuiltinFnIdRem,
BuiltinFnIdMod,
BuiltinFnIdSqrt,
+ BuiltinFnIdSin,
+ BuiltinFnIdCos,
+ BuiltinFnIdExp,
+ BuiltinFnIdExp2,
+ BuiltinFnIdLn,
+ BuiltinFnIdLog2,
+ BuiltinFnIdLog10,
+ BuiltinFnIdFabs,
+ BuiltinFnIdFloor,
+ BuiltinFnIdCeil,
+ BuiltinFnIdTrunc,
+ BuiltinFnIdNearbyInt,
+ BuiltinFnIdRound,
BuiltinFnIdTruncate,
BuiltinFnIdIntCast,
BuiltinFnIdFloatCast,
@@ -1556,9 +1569,7 @@ enum ZigLLVMFnId {
ZigLLVMFnIdPopCount,
ZigLLVMFnIdOverflowArithmetic,
ZigLLVMFnIdFMA,
- ZigLLVMFnIdFloor,
- ZigLLVMFnIdCeil,
- ZigLLVMFnIdSqrt,
+ ZigLLVMFnIdFloatOp,
ZigLLVMFnIdBswap,
ZigLLVMFnIdBitReverse,
};
@@ -1585,6 +1596,7 @@ struct ZigLLVMFnKey {
uint32_t bit_count;
} pop_count;
struct {
+ BuiltinFnId op;
uint32_t bit_count;
uint32_t vector_len; // 0 means not a vector
} floating;
@@ -2239,6 +2251,7 @@ enum IrInstructionId {
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdMulAdd,
+ IrInstructionIdFloatOp,
IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
@@ -2300,7 +2313,6 @@ enum IrInstructionId {
IrInstructionIdAddImplicitReturnType,
IrInstructionIdMergeErrRetTraces,
IrInstructionIdMarkErrRetTracePtr,
- IrInstructionIdSqrt,
IrInstructionIdErrSetCast,
IrInstructionIdToBytes,
IrInstructionIdFromBytes,
@@ -3474,11 +3486,13 @@ struct IrInstructionMarkErrRetTracePtr {
IrInstruction *err_ret_trace_ptr;
};
-struct IrInstructionSqrt {
+// For float ops which take a single argument
+struct IrInstructionFloatOp {
IrInstruction base;
+ BuiltinFnId op;
IrInstruction *type;
- IrInstruction *op;
+ IrInstruction *op1;
};
struct IrInstructionCheckRuntimeScope {
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 15b42c7f9d..13b35e0aff 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -5736,9 +5736,10 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
return (uint32_t)(x.data.clz.bit_count) * (uint32_t)2428952817;
case ZigLLVMFnIdPopCount:
return (uint32_t)(x.data.clz.bit_count) * (uint32_t)101195049;
- case ZigLLVMFnIdFloor:
- case ZigLLVMFnIdCeil:
- case ZigLLVMFnIdSqrt:
+ case ZigLLVMFnIdFloatOp:
+ return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
+ (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025) +
+ (uint32_t)(x.data.floating.op) * (uint32_t)43789879;
case ZigLLVMFnIdFMA:
return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
(uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025);
@@ -5769,10 +5770,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
return a.data.bswap.bit_count == b.data.bswap.bit_count;
case ZigLLVMFnIdBitReverse:
return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
- case ZigLLVMFnIdFloor:
- case ZigLLVMFnIdCeil:
- case ZigLLVMFnIdSqrt:
- return a.data.floating.bit_count == b.data.floating.bit_count;
+ case ZigLLVMFnIdFloatOp:
+ return a.data.floating.bit_count == b.data.floating.bit_count &&
+ a.data.floating.vector_len == b.data.floating.vector_len &&
+ a.data.floating.op == b.data.floating.op;
case ZigLLVMFnIdFMA:
return a.data.floating.bit_count == b.data.floating.bit_count &&
a.data.floating.vector_len == b.data.floating.vector_len;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 6691652a5e..41caa29dbd 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -806,7 +806,7 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSu
return fn_val;
}
-static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id) {
+static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id, BuiltinFnId op) {
assert(type_entry->id == ZigTypeIdFloat ||
type_entry->id == ZigTypeIdVector);
@@ -817,6 +817,7 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn
key.id = fn_id;
key.data.floating.bit_count = (uint32_t)float_type->data.floating.bit_count;
key.data.floating.vector_len = is_vector ? (uint32_t)type_entry->data.vector.len : 0;
+ key.data.floating.op = op;
auto existing_entry = g->llvm_fn_table.maybe_get(key);
if (existing_entry)
@@ -824,18 +825,12 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn
const char *name;
uint32_t num_args;
- if (fn_id == ZigLLVMFnIdFloor) {
- name = "floor";
- num_args = 1;
- } else if (fn_id == ZigLLVMFnIdCeil) {
- name = "ceil";
- num_args = 1;
- } else if (fn_id == ZigLLVMFnIdSqrt) {
- name = "sqrt";
- num_args = 1;
- } else if (fn_id == ZigLLVMFnIdFMA) {
+ if (fn_id == ZigLLVMFnIdFMA) {
name = "fma";
num_args = 3;
+ } else if (fn_id == ZigLLVMFnIdFloatOp) {
+ name = float_op_to_name(op, true);
+ num_args = 1;
} else {
zig_unreachable();
}
@@ -2480,22 +2475,17 @@ static LLVMValueRef gen_overflow_shr_op(CodeGen *g, ZigType *type_entry,
return result;
}
-static LLVMValueRef gen_floor(CodeGen *g, LLVMValueRef val, ZigType *type_entry) {
- if (type_entry->id == ZigTypeIdInt)
+static LLVMValueRef gen_float_op(CodeGen *g, LLVMValueRef val, ZigType *type_entry, BuiltinFnId op) {
+ if ((op == BuiltinFnIdCeil ||
+ op == BuiltinFnIdFloor) &&
+ type_entry->id == ZigTypeIdInt)
return val;
+ assert(type_entry->id == ZigTypeIdFloat);
- LLVMValueRef floor_fn = get_float_fn(g, type_entry, ZigLLVMFnIdFloor);
+ LLVMValueRef floor_fn = get_float_fn(g, type_entry, ZigLLVMFnIdFloatOp, op);
return LLVMBuildCall(g->builder, floor_fn, &val, 1, "");
}
-static LLVMValueRef gen_ceil(CodeGen *g, LLVMValueRef val, ZigType *type_entry) {
- if (type_entry->id == ZigTypeIdInt)
- return val;
-
- LLVMValueRef ceil_fn = get_float_fn(g, type_entry, ZigLLVMFnIdCeil);
- return LLVMBuildCall(g->builder, ceil_fn, &val, 1, "");
-}
-
enum DivKind {
DivKindFloat,
DivKindTrunc,
@@ -2571,7 +2561,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
return result;
case DivKindExact:
if (want_runtime_safety) {
- LLVMValueRef floored = gen_floor(g, result, type_entry);
+ LLVMValueRef floored = gen_float_op(g, result, type_entry, BuiltinFnIdFloor);
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
LLVMValueRef ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, floored, result, "");
@@ -2593,12 +2583,12 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
LLVMBuildCondBr(g->builder, ltz, ltz_block, gez_block);
LLVMPositionBuilderAtEnd(g->builder, ltz_block);
- LLVMValueRef ceiled = gen_ceil(g, result, type_entry);
+ LLVMValueRef ceiled = gen_float_op(g, result, type_entry, BuiltinFnIdCeil);
LLVMBasicBlockRef ceiled_end_block = LLVMGetInsertBlock(g->builder);
LLVMBuildBr(g->builder, end_block);
LLVMPositionBuilderAtEnd(g->builder, gez_block);
- LLVMValueRef floored = gen_floor(g, result, type_entry);
+ LLVMValueRef floored = gen_float_op(g, result, type_entry, BuiltinFnIdFloor);
LLVMBasicBlockRef floored_end_block = LLVMGetInsertBlock(g->builder);
LLVMBuildBr(g->builder, end_block);
@@ -2610,7 +2600,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
return phi;
}
case DivKindFloor:
- return gen_floor(g, result, type_entry);
+ return gen_float_op(g, result, type_entry, BuiltinFnIdFloor);
}
zig_unreachable();
}
@@ -5450,10 +5440,10 @@ static LLVMValueRef ir_render_mark_err_ret_trace_ptr(CodeGen *g, IrExecutable *e
return nullptr;
}
-static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstructionSqrt *instruction) {
- LLVMValueRef op = ir_llvm_value(g, instruction->op);
+static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {
+ LLVMValueRef op = ir_llvm_value(g, instruction->op1);
assert(instruction->base.value.type->id == ZigTypeIdFloat);
- LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdSqrt);
+ LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdFloatOp, instruction->op);
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
}
@@ -5463,7 +5453,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrIn
LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
assert(instruction->base.value.type->id == ZigTypeIdFloat ||
instruction->base.value.type->id == ZigTypeIdVector);
- LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdFMA);
+ LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd);
LLVMValueRef args[3] = {
op1,
op2,
@@ -5814,8 +5804,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_merge_err_ret_traces(g, executable, (IrInstructionMergeErrRetTraces *)instruction);
case IrInstructionIdMarkErrRetTracePtr:
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
- case IrInstructionIdSqrt:
- return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdFloatOp:
+ return ir_render_float_op(g, executable, (IrInstructionFloatOp *)instruction);
case IrInstructionIdMulAdd:
return ir_render_mul_add(g, executable, (IrInstructionMulAdd *)instruction);
case IrInstructionIdArrayToVector:
@@ -7435,6 +7425,20 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);
+ create_builtin_fn(g, BuiltinFnIdSin, "sin", 2);
+ create_builtin_fn(g, BuiltinFnIdCos, "cos", 2);
+ create_builtin_fn(g, BuiltinFnIdExp, "exp", 2);
+ create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 2);
+ create_builtin_fn(g, BuiltinFnIdLn, "ln", 2);
+ create_builtin_fn(g, BuiltinFnIdLog2, "log2", 2);
+ create_builtin_fn(g, BuiltinFnIdLog10, "log10", 2);
+ create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 2);
+ create_builtin_fn(g, BuiltinFnIdFloor, "floor", 2);
+ create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 2);
+ create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 2);
+ //Needs library support on Windows
+ //create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);
+ create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
diff --git a/src/ir.cpp b/src/ir.cpp
index c2c6cb6154..50d2a06868 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -991,8 +991,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMarkErrRetTraceP
return IrInstructionIdMarkErrRetTracePtr;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
- return IrInstructionIdSqrt;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatOp *) {
+ return IrInstructionIdFloatOp;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
@@ -2312,6 +2312,59 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+
+//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign,
+// lround, llround, lrint, llrint
+// So far this is only non-complicated type functions.
+const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {
+ const bool b = llvm_name;
+
+ switch (op) {
+ case BuiltinFnIdSqrt:
+ return "sqrt";
+ case BuiltinFnIdSin:
+ return "sin";
+ case BuiltinFnIdCos:
+ return "cos";
+ case BuiltinFnIdExp:
+ return "exp";
+ case BuiltinFnIdExp2:
+ return "exp2";
+ case BuiltinFnIdLn:
+ return b ? "log" : "ln";
+ case BuiltinFnIdLog10:
+ return "log10";
+ case BuiltinFnIdLog2:
+ return "log2";
+ case BuiltinFnIdFabs:
+ return "fabs";
+ case BuiltinFnIdFloor:
+ return "floor";
+ case BuiltinFnIdCeil:
+ return "ceil";
+ case BuiltinFnIdTrunc:
+ return "trunc";
+ case BuiltinFnIdNearbyInt:
+ return b ? "nearbyint" : "nearbyInt";
+ case BuiltinFnIdRound:
+ return "round";
+ default:
+ zig_unreachable();
+ }
+}
+
+static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op1, BuiltinFnId op) {
+ IrInstructionFloatOp *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->type = type;
+ instruction->op1 = op1;
+ instruction->op = op;
+
+ if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+ ir_ref_instruction(op1, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_mul_add(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, IrInstruction *op3) {
IrInstructionMulAdd *instruction = ir_build_instruction(irb, scope, source_node);
@@ -3033,17 +3086,6 @@ static IrInstruction *ir_build_mark_err_ret_trace_ptr(IrBuilder *irb, Scope *sco
return &instruction->base;
}
-static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
- IrInstructionSqrt *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->type = type;
- instruction->op = op;
-
- if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
- ir_ref_instruction(op, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *container, IrInstruction *name)
{
@@ -4400,6 +4442,19 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_lval_wrap(irb, scope, bin_op, lval);
}
case BuiltinFnIdSqrt:
+ case BuiltinFnIdSin:
+ case BuiltinFnIdCos:
+ case BuiltinFnIdExp:
+ case BuiltinFnIdExp2:
+ case BuiltinFnIdLn:
+ case BuiltinFnIdLog2:
+ case BuiltinFnIdLog10:
+ case BuiltinFnIdFabs:
+ case BuiltinFnIdFloor:
+ case BuiltinFnIdCeil:
+ case BuiltinFnIdTrunc:
+ case BuiltinFnIdNearbyInt:
+ case BuiltinFnIdRound:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
@@ -4411,7 +4466,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *ir_sqrt = ir_build_sqrt(irb, scope, node, arg0_value, arg1_value);
+ IrInstruction *ir_sqrt = ir_build_float_op(irb, scope, node, arg0_value, arg1_value, builtin_fn->id);
return ir_lval_wrap(irb, scope, ir_sqrt, lval);
}
case BuiltinFnIdTruncate:
@@ -23214,70 +23269,248 @@ static IrInstruction *ir_analyze_instruction_mark_err_ret_trace_ptr(IrAnalyze *i
return result;
}
-static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionSqrt *instruction) {
- ZigType *float_type = ir_resolve_type(ira, instruction->type->child);
- if (type_is_invalid(float_type))
- return ira->codegen->invalid_instruction;
+static void ir_eval_float_op(IrAnalyze *ira, IrInstructionFloatOp *source_instr, ZigType *float_type,
+ ConstExprValue *op, ConstExprValue *out_val) {
+ assert(ira && source_instr && float_type && out_val && op);
+ assert(float_type->id == ZigTypeIdFloat ||
+ float_type->id == ZigTypeIdComptimeFloat);
- IrInstruction *op = instruction->op->child;
- if (type_is_invalid(op->value.type))
+ BuiltinFnId fop = source_instr->op;
+ unsigned bits;
+
+ if (float_type->id == ZigTypeIdComptimeFloat) {
+ bits = 128;
+ } else if (float_type->id == ZigTypeIdFloat)
+ bits = float_type->data.floating.bit_count;
+
+ switch (bits) {
+ case 16: {
+ switch (fop) {
+ case BuiltinFnIdSqrt:
+ out_val->data.x_f16 = f16_sqrt(op->data.x_f16);
+ break;
+ case BuiltinFnIdSin:
+ case BuiltinFnIdCos:
+ case BuiltinFnIdExp:
+ case BuiltinFnIdExp2:
+ case BuiltinFnIdLn:
+ case BuiltinFnIdLog10:
+ case BuiltinFnIdLog2:
+ case BuiltinFnIdFabs:
+ case BuiltinFnIdFloor:
+ case BuiltinFnIdCeil:
+ case BuiltinFnIdTrunc:
+ case BuiltinFnIdNearbyInt:
+ case BuiltinFnIdRound:
+ zig_panic("unimplemented f16 builtin");
+ default:
+ zig_unreachable();
+ };
+ break;
+ };
+ case 32: {
+ switch (fop) {
+ case BuiltinFnIdSqrt:
+ out_val->data.x_f32 = sqrtf(op->data.x_f32);
+ break;
+ case BuiltinFnIdSin:
+ out_val->data.x_f32 = sinf(op->data.x_f32);
+ break;
+ case BuiltinFnIdCos:
+ out_val->data.x_f32 = cosf(op->data.x_f32);
+ break;
+ case BuiltinFnIdExp:
+ out_val->data.x_f32 = expf(op->data.x_f32);
+ break;
+ case BuiltinFnIdExp2:
+ out_val->data.x_f32 = exp2f(op->data.x_f32);
+ break;
+ case BuiltinFnIdLn:
+ out_val->data.x_f32 = logf(op->data.x_f32);
+ break;
+ case BuiltinFnIdLog10:
+ out_val->data.x_f32 = log10f(op->data.x_f32);
+ break;
+ case BuiltinFnIdLog2:
+ out_val->data.x_f32 = log2f(op->data.x_f32);
+ break;
+ case BuiltinFnIdFabs:
+ out_val->data.x_f32 = fabsf(op->data.x_f32);
+ break;
+ case BuiltinFnIdFloor:
+ out_val->data.x_f32 = floorf(op->data.x_f32);
+ break;
+ case BuiltinFnIdCeil:
+ out_val->data.x_f32 = ceilf(op->data.x_f32);
+ break;
+ case BuiltinFnIdTrunc:
+ out_val->data.x_f32 = truncf(op->data.x_f32);
+ break;
+ case BuiltinFnIdNearbyInt:
+ out_val->data.x_f32 = nearbyintf(op->data.x_f32);
+ break;
+ case BuiltinFnIdRound:
+ out_val->data.x_f32 = roundf(op->data.x_f32);
+ break;
+ default:
+ zig_unreachable();
+ };
+ break;
+ };
+ case 64: {
+ switch (fop) {
+ case BuiltinFnIdSqrt:
+ out_val->data.x_f64 = sqrt(op->data.x_f64);
+ break;
+ case BuiltinFnIdSin:
+ out_val->data.x_f64 = sin(op->data.x_f64);
+ break;
+ case BuiltinFnIdCos:
+ out_val->data.x_f64 = cos(op->data.x_f64);
+ break;
+ case BuiltinFnIdExp:
+ out_val->data.x_f64 = exp(op->data.x_f64);
+ break;
+ case BuiltinFnIdExp2:
+ out_val->data.x_f64 = exp2(op->data.x_f64);
+ break;
+ case BuiltinFnIdLn:
+ out_val->data.x_f64 = log(op->data.x_f64);
+ break;
+ case BuiltinFnIdLog10:
+ out_val->data.x_f64 = log10(op->data.x_f64);
+ break;
+ case BuiltinFnIdLog2:
+ out_val->data.x_f64 = log2(op->data.x_f64);
+ break;
+ case BuiltinFnIdFabs:
+ out_val->data.x_f64 = fabs(op->data.x_f64);
+ break;
+ case BuiltinFnIdFloor:
+ out_val->data.x_f64 = floor(op->data.x_f64);
+ break;
+ case BuiltinFnIdCeil:
+ out_val->data.x_f64 = ceil(op->data.x_f64);
+ break;
+ case BuiltinFnIdTrunc:
+ out_val->data.x_f64 = trunc(op->data.x_f64);
+ break;
+ case BuiltinFnIdNearbyInt:
+ out_val->data.x_f64 = nearbyint(op->data.x_f64);
+ break;
+ case BuiltinFnIdRound:
+ out_val->data.x_f64 = round(op->data.x_f64);
+ break;
+ default:
+ zig_unreachable();
+ }
+ break;
+ };
+ case 128: {
+ float128_t *out, *in;
+ if (float_type->id == ZigTypeIdComptimeFloat) {
+ out = &out_val->data.x_bigfloat.value;
+ in = &op->data.x_bigfloat.value;
+ } else {
+ out = &out_val->data.x_f128;
+ in = &op->data.x_f128;
+ }
+ switch (fop) {
+ case BuiltinFnIdSqrt:
+ f128M_sqrt(in, out);
+ break;
+ case BuiltinFnIdNearbyInt:
+ case BuiltinFnIdSin:
+ case BuiltinFnIdCos:
+ case BuiltinFnIdExp:
+ case BuiltinFnIdExp2:
+ case BuiltinFnIdLn:
+ case BuiltinFnIdLog10:
+ case BuiltinFnIdLog2:
+ case BuiltinFnIdFabs:
+ case BuiltinFnIdFloor:
+ case BuiltinFnIdCeil:
+ case BuiltinFnIdTrunc:
+ case BuiltinFnIdRound:
+ zig_panic("unimplemented f128 builtin");
+ default:
+ zig_unreachable();
+ }
+ break;
+ };
+ default:
+ zig_unreachable();
+ }
+}
+
+static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) {
+ IrInstruction *type = instruction->type->child;
+ if (type_is_invalid(type->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ZigType *expr_type = ir_resolve_type(ira, type);
+ if (type_is_invalid(expr_type))
return ira->codegen->invalid_instruction;
- bool ok_type = float_type->id == ZigTypeIdComptimeFloat || float_type->id == ZigTypeIdFloat;
- if (!ok_type) {
- ir_add_error(ira, instruction->type, buf_sprintf("@sqrt does not support type '%s'", buf_ptr(&float_type->name)));
+ // Only allow float types, and vectors of floats.
+ ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
+ if (float_type->id != ZigTypeIdFloat && float_type->id != ZigTypeIdComptimeFloat) {
+ ir_add_error(ira, instruction->type, buf_sprintf("@%s does not support type '%s'", float_op_to_name(instruction->op, false), buf_ptr(&float_type->name)));
return ira->codegen->invalid_instruction;
}
- IrInstruction *casted_op = ir_implicit_cast(ira, op, float_type);
- if (type_is_invalid(casted_op->value.type))
+ IrInstruction *op1 = instruction->op1->child;
+ if (type_is_invalid(op1->value.type))
return ira->codegen->invalid_instruction;
- if (instr_is_comptime(casted_op)) {
- ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
- if (!val)
+ IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, float_type);
+ if (type_is_invalid(casted_op1->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (instr_is_comptime(casted_op1)) {
+ // Our comptime 16-bit and 128-bit support is quite limited.
+ if ((float_type->id == ZigTypeIdComptimeFloat ||
+ float_type->data.floating.bit_count == 16 ||
+ float_type->data.floating.bit_count == 128) &&
+ instruction->op != BuiltinFnIdSqrt) {
+ ir_add_error(ira, instruction->type, buf_sprintf("@%s does not support type '%s'", float_op_to_name(instruction->op, false), buf_ptr(&float_type->name)));
return ira->codegen->invalid_instruction;
+ }
- IrInstruction *result = ir_const(ira, &instruction->base, float_type);
+ ConstExprValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad);
+ if (!op1_const)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
ConstExprValue *out_val = &result->value;
- if (float_type->id == ZigTypeIdComptimeFloat) {
- bigfloat_sqrt(&out_val->data.x_bigfloat, &val->data.x_bigfloat);
- } else if (float_type->id == ZigTypeIdFloat) {
- switch (float_type->data.floating.bit_count) {
- case 16:
- out_val->data.x_f16 = f16_sqrt(val->data.x_f16);
- break;
- case 32:
- out_val->data.x_f32 = sqrtf(val->data.x_f32);
- break;
- case 64:
- out_val->data.x_f64 = sqrt(val->data.x_f64);
- break;
- case 128:
- f128M_sqrt(&val->data.x_f128, &out_val->data.x_f128);
- break;
- default:
- zig_unreachable();
+ if (expr_type->id == ZigTypeIdVector) {
+ expand_undef_array(ira->codegen, op1_const);
+ out_val->special = ConstValSpecialUndef;
+ expand_undef_array(ira->codegen, out_val);
+ size_t len = expr_type->data.vector.len;
+ for (size_t i = 0; i < len; i += 1) {
+ ConstExprValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];
+ ConstExprValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
+ assert(float_operand_op1->type == float_type);
+ assert(float_out_val->type == float_type);
+ ir_eval_float_op(ira, instruction, float_type,
+ op1_const, float_out_val);
+ float_out_val->type = float_type;
}
+ out_val->type = expr_type;
+ out_val->special = ConstValSpecialStatic;
} else {
- zig_unreachable();
+ ir_eval_float_op(ira, instruction, float_type, op1_const, out_val);
}
-
return result;
}
ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base);
- if (float_type->data.floating.bit_count != 16 &&
- float_type->data.floating.bit_count != 32 &&
- float_type->data.floating.bit_count != 64) {
- ir_add_error(ira, instruction->type, buf_sprintf("compiler TODO: add implementation of sqrt for '%s'", buf_ptr(&float_type->name)));
- return ira->codegen->invalid_instruction;
- }
- IrInstruction *result = ir_build_sqrt(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, casted_op);
- result->value.type = float_type;
+ IrInstruction *result = ir_build_float_op(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr, casted_op1, instruction->op);
+ result->value.type = expr_type;
return result;
}
@@ -23762,8 +23995,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_merge_err_ret_traces(ira, (IrInstructionMergeErrRetTraces *)instruction);
case IrInstructionIdMarkErrRetTracePtr:
return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
- case IrInstructionIdSqrt:
- return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdFloatOp:
+ return ir_analyze_instruction_float_op(ira, (IrInstructionFloatOp *)instruction);
case IrInstructionIdMulAdd:
return ir_analyze_instruction_mul_add(ira, (IrInstructionMulAdd *)instruction);
case IrInstructionIdIntToErr:
@@ -24004,7 +24237,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCoroFree:
case IrInstructionIdCoroPromise:
case IrInstructionIdPromiseResultType:
- case IrInstructionIdSqrt:
+ case IrInstructionIdFloatOp:
case IrInstructionIdMulAdd:
case IrInstructionIdAtomicLoad:
case IrInstructionIdIntCast:
diff --git a/src/ir.hpp b/src/ir.hpp
index 4fb7552212..597624e2e6 100644
--- a/src/ir.hpp
+++ b/src/ir.hpp
@@ -26,5 +26,6 @@ bool ir_has_side_effects(IrInstruction *instruction);
struct IrAnalyze;
ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,
AstNode *source_node);
+const char *float_op_to_name(BuiltinFnId op, bool llvm_name);
#endif
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index e205c8e067..165d9b4739 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1427,15 +1427,16 @@ static void ir_print_mark_err_ret_trace_ptr(IrPrint *irp, IrInstructionMarkErrRe
fprintf(irp->f, ")");
}
-static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
- fprintf(irp->f, "@sqrt(");
+static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) {
+
+ fprintf(irp->f, "@%s(", float_op_to_name(instruction->op, false));
if (instruction->type != nullptr) {
ir_print_other_instruction(irp, instruction->type);
} else {
fprintf(irp->f, "null");
}
fprintf(irp->f, ",");
- ir_print_other_instruction(irp, instruction->op);
+ ir_print_other_instruction(irp, instruction->op1);
fprintf(irp->f, ")");
}
@@ -1918,8 +1919,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdMarkErrRetTracePtr:
ir_print_mark_err_ret_trace_ptr(irp, (IrInstructionMarkErrRetTracePtr *)instruction);
break;
- case IrInstructionIdSqrt:
- ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdFloatOp:
+ ir_print_float_op(irp, (IrInstructionFloatOp *)instruction);
break;
case IrInstructionIdMulAdd:
ir_print_mul_add(irp, (IrInstructionMulAdd *)instruction);
diff --git a/src/util.cpp b/src/util.cpp
index 9a6a382993..f85565806f 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -13,6 +13,7 @@
#include "userland.h"
void zig_panic(const char *format, ...) {
+ abort();
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
diff --git a/std/special/c.zig b/std/special/c.zig
index b3cf54619f..15cefbd2a0 100644
--- a/std/special/c.zig
+++ b/std/special/c.zig
@@ -254,24 +254,32 @@ export fn fmod(x: f64, y: f64) f64 {
// TODO add intrinsics for these (and probably the double version too)
// and have the math stuff use the intrinsic. same as @mod and @rem
-export fn floorf(x: f32) f32 {
- return math.floor(x);
-}
-export fn ceilf(x: f32) f32 {
- return math.ceil(x);
-}
-export fn floor(x: f64) f64 {
- return math.floor(x);
-}
-export fn ceil(x: f64) f64 {
- return math.ceil(x);
-}
-export fn fma(a: f64, b: f64, c: f64) f64 {
- return math.fma(f64, a, b, c);
-}
-export fn fmaf(a: f32, b: f32, c: f32) f32 {
- return math.fma(f32, a, b, c);
-}
+export fn floorf(x: f32) f32 {return math.floor(x);}
+export fn ceilf(x: f32) f32 {return math.ceil(x);}
+export fn floor(x: f64) f64 {return math.floor(x);}
+export fn ceil(x: f64) f64 {return math.ceil(x);}
+export fn fma(a: f64, b: f64, c: f64) f64 {return math.fma(f64, a, b, c);}
+export fn fmaf(a: f32, b: f32, c: f32) f32 {return math.fma(f32, a, b, c);}
+export fn sin(a: f64) f64 {return math.sin(a);}
+export fn sinf(a: f32) f32 {return math.sin(a);}
+export fn cos(a: f64) f64 {return math.cos(a);}
+export fn cosf(a: f32) f32 {return math.cos(a);}
+export fn exp(a: f64) f64 {return math.exp(a);}
+export fn expf(a: f32) f32 {return math.exp(a);}
+export fn exp2(a: f64) f64 {return math.exp2(a);}
+export fn exp2f(a: f32) f32 {return math.exp2(a);}
+export fn log(a: f64) f64 {return math.ln(a);}
+export fn logf(a: f32) f32 {return math.ln(a);}
+export fn log2(a: f64) f64 {return math.log2(a);}
+export fn log2f(a: f32) f32 {return math.log2(a);}
+export fn log10(a: f64) f64 {return math.log10(a);}
+export fn log10f(a: f32) f32 {return math.log10(a);}
+export fn fabs(a: f64) f64 {return math.fabs(a);}
+export fn fabsf(a: f32) f32 {return math.fabs(a);}
+export fn trunc(a: f64) f64 {return math.trunc(a);}
+export fn truncf(a: f32) f32 {return math.trunc(a);}
+export fn round(a: f64) f64 {return math.round(a);}
+export fn roundf(a: f32) f32 {return math.round(a);}
fn generic_fmod(comptime T: type, x: T, y: T) T {
@setRuntimeSafety(false);
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 10e7c1a09b..efefed33ba 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -71,6 +71,7 @@ comptime {
_ = @import("behavior/pointers.zig");
_ = @import("behavior/popcount.zig");
_ = @import("behavior/muladd.zig");
+ _ = @import("behavior/floatop.zig");
_ = @import("behavior/ptrcast.zig");
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
diff --git a/test/stage1/behavior/floatop.zig b/test/stage1/behavior/floatop.zig
new file mode 100644
index 0000000000..de2f6815a6
--- /dev/null
+++ b/test/stage1/behavior/floatop.zig
@@ -0,0 +1,243 @@
+const expect = @import("std").testing.expect;
+const pi = @import("std").math.pi;
+const e = @import("std").math.e;
+
+test "@sqrt" {
+ comptime testSqrt();
+ testSqrt();
+}
+
+fn testSqrt() void {
+ {
+ var a: f16 = 4;
+ expect(@sqrt(f16, a) == 2);
+ }
+ {
+ var a: f32 = 9;
+ expect(@sqrt(f32, a) == 3);
+ }
+ {
+ var a: f64 = 25;
+ expect(@sqrt(f64, a) == 5);
+ }
+ {
+ const a: comptime_float = 25.0;
+ expect(@sqrt(comptime_float, a) == 5.0);
+ }
+ // Waiting on a c.zig implementation
+ //{
+ // var a: f128 = 49;
+ // expect(@sqrt(f128, a) == 7);
+ //}
+}
+
+test "@sin" {
+ comptime testSin();
+ testSin();
+}
+
+fn testSin() void {
+ // TODO - this is actually useful and should be implemented
+ // (all the trig functions for f16)
+ // but will probably wait till self-hosted
+ //{
+ // var a: f16 = pi;
+ // expect(@sin(f16, a/2) == 1);
+ //}
+ {
+ var a: f32 = 0;
+ expect(@sin(f32, a) == 0);
+ }
+ {
+ var a: f64 = 0;
+ expect(@sin(f64, a) == 0);
+ }
+ // TODO
+ //{
+ // var a: f16 = pi;
+ // expect(@sqrt(f128, a/2) == 1);
+ //}
+}
+
+test "@cos" {
+ comptime testCos();
+ testCos();
+}
+
+fn testCos() void {
+ {
+ var a: f32 = 0;
+ expect(@cos(f32, a) == 1);
+ }
+ {
+ var a: f64 = 0;
+ expect(@cos(f64, a) == 1);
+ }
+}
+
+test "@exp" {
+ comptime testExp();
+ testExp();
+}
+
+fn testExp() void {
+ {
+ var a: f32 = 0;
+ expect(@exp(f32, a) == 1);
+ }
+ {
+ var a: f64 = 0;
+ expect(@exp(f64, a) == 1);
+ }
+}
+
+test "@exp2" {
+ comptime testExp2();
+ testExp2();
+}
+
+fn testExp2() void {
+ {
+ var a: f32 = 2;
+ expect(@exp2(f32, a) == 4);
+ }
+ {
+ var a: f64 = 2;
+ expect(@exp2(f64, a) == 4);
+ }
+}
+
+test "@ln" {
+ // Old musl (and glibc?), and our current math.ln implementation do not return 1
+ // so also accept those values.
+ comptime testLn();
+ testLn();
+}
+
+fn testLn() void {
+ {
+ var a: f32 = e;
+ expect(@ln(f32, a) == 1 or @ln(f32, a) == @bitCast(f32, u32(0x3f7fffff)));
+ }
+ {
+ var a: f64 = e;
+ expect(@ln(f64, a) == 1 or @ln(f64, a) == @bitCast(f64, u64(0x3ff0000000000000)));
+ }
+}
+
+test "@log2" {
+ comptime testLog2();
+ testLog2();
+}
+
+fn testLog2() void {
+ {
+ var a: f32 = 4;
+ expect(@log2(f32, a) == 2);
+ }
+ {
+ var a: f64 = 4;
+ expect(@log2(f64, a) == 2);
+ }
+}
+
+test "@log10" {
+ comptime testLog10();
+ testLog10();
+}
+
+fn testLog10() void {
+ {
+ var a: f32 = 100;
+ expect(@log10(f32, a) == 2);
+ }
+ {
+ var a: f64 = 1000;
+ expect(@log10(f64, a) == 3);
+ }
+}
+
+test "@fabs" {
+ comptime testFabs();
+ testFabs();
+}
+
+fn testFabs() void {
+ {
+ var a: f32 = -2.5;
+ var b: f32 = 2.5;
+ expect(@fabs(f32, a) == 2.5);
+ expect(@fabs(f32, b) == 2.5);
+ }
+ {
+ var a: f64 = -2.5;
+ var b: f64 = 2.5;
+ expect(@fabs(f64, a) == 2.5);
+ expect(@fabs(f64, b) == 2.5);
+ }
+}
+
+test "@floor" {
+ comptime testFloor();
+ testFloor();
+}
+
+fn testFloor() void {
+ {
+ var a: f32 = 2.1;
+ expect(@floor(f32, a) == 2);
+ }
+ {
+ var a: f64 = 3.5;
+ expect(@floor(f64, a) == 3);
+ }
+}
+
+test "@ceil" {
+ comptime testCeil();
+ testCeil();
+}
+
+fn testCeil() void {
+ {
+ var a: f32 = 2.1;
+ expect(@ceil(f32, a) == 3);
+ }
+ {
+ var a: f64 = 3.5;
+ expect(@ceil(f64, a) == 4);
+ }
+}
+
+test "@trunc" {
+ comptime testTrunc();
+ testTrunc();
+}
+
+fn testTrunc() void {
+ {
+ var a: f32 = 2.1;
+ expect(@trunc(f32, a) == 2);
+ }
+ {
+ var a: f64 = -3.5;
+ expect(@trunc(f64, a) == -3);
+ }
+}
+
+// This is waiting on library support for the Windows build (not sure why the other's don't need it)
+//test "@nearbyInt" {
+// comptime testNearbyInt();
+// testNearbyInt();
+//}
+
+//fn testNearbyInt() void {
+// {
+// var a: f32 = 2.1;
+// expect(@nearbyInt(f32, a) == 2);
+// }
+// {
+// var a: f64 = -3.75;
+// expect(@nearbyInt(f64, a) == -4);
+// }
+//}
--
cgit v1.2.3
From 86f362ce8e878188d40393e6f2feba0c60ddbcf0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 22 Jun 2019 16:18:42 -0400
Subject: elide redundant safety check when switching on tagged unions
---
src/all_types.hpp | 1 +
src/codegen.cpp | 2 +-
src/ir.cpp | 9 +++++----
std/zig/render.zig | 6 +++---
4 files changed, 10 insertions(+), 8 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 213a64dd9d..5b75d9f96a 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2540,6 +2540,7 @@ struct IrInstructionStructFieldPtr {
struct IrInstructionUnionFieldPtr {
IrInstruction base;
+ bool safety_check_on;
bool initializing;
IrInstruction *union_ptr;
TypeUnionField *field;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 5b7169f312..4eea729dd9 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3890,7 +3890,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
&field->enum_field->value);
gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
- } else if (ir_want_runtime_safety(g, &instruction->base)) {
+ } else if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
diff --git a/src/ir.cpp b/src/ir.cpp
index e943788f97..823ddb13a3 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1384,10 +1384,11 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As
}
static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *union_ptr, TypeUnionField *field, bool initializing)
+ IrInstruction *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing)
{
IrInstructionUnionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node);
instruction->initializing = initializing;
+ instruction->safety_check_on = safety_check_on;
instruction->union_ptr = union_ptr;
instruction->field = field;
@@ -17514,7 +17515,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
IrInstruction *result;
if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
- source_instr->source_node, container_ptr, field, initializing);
+ source_instr->source_node, container_ptr, field, true, initializing);
result->value.type = ptr_type;
result->value.special = ConstValSpecialStatic;
} else {
@@ -17529,7 +17530,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
}
IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
- source_instr->source_node, container_ptr, field, initializing);
+ source_instr->source_node, container_ptr, field, true, initializing);
result->value.type = ptr_type;
return result;
}
@@ -19005,7 +19006,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
}
IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, target_value_ptr, field, false);
+ instruction->base.scope, instruction->base.source_node, target_value_ptr, field, false, false);
result->value.type = get_pointer_to_type(ira->codegen, field->type_entry,
target_value_ptr->value.type->data.pointer.is_const);
return result;
diff --git a/std/zig/render.zig b/std/zig/render.zig
index ef5c8f2346..2e8e4481be 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -939,10 +939,10 @@ fn renderExpression(
}
switch (container_decl.init_arg_expr) {
- ast.Node.ContainerDecl.InitArg.None => {
+ .None => {
try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
},
- ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
+ .Enum => |enum_tag_type| {
try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
const lparen = tree.nextToken(container_decl.kind_token);
@@ -962,7 +962,7 @@ fn renderExpression(
try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // )
}
},
- ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
+ .Type => |type_expr| {
try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
const lparen = tree.nextToken(container_decl.kind_token);
--
cgit v1.2.3
From 3021e5ca67acca6cf7420bc5e2400aa6965596f9 Mon Sep 17 00:00:00 2001
From: Michael Dusan
Date: Mon, 24 Jun 2019 14:38:22 -0400
Subject: align (vector -> array) store to result location
---
src/codegen.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 4eea729dd9..e12f89756d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5451,7 +5451,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
- gen_store_untyped(g, vector, casted_ptr, 0, false);
+ gen_store_untyped(g, vector, casted_ptr, get_ptr_align(g, instruction->result_loc->value.type), false);
return result_loc;
}
--
cgit v1.2.3
From c61e0a078cea2a6845ed7b03189409829d2cdf24 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Jun 2019 11:31:38 -0400
Subject: fix union init with void payload
all std lib tests passing now
---
src/analyze.cpp | 14 +++-----------
src/analyze.hpp | 1 -
src/codegen.cpp | 14 +++++++++++++-
src/ir.cpp | 18 +++++++-----------
std/zig/parser_test.zig | 12 +-----------
test/stage1/behavior/union.zig | 20 ++++++++++++++++++++
6 files changed, 44 insertions(+), 35 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 85e390f2e0..d3a9376c5d 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -5001,12 +5001,9 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
field_val->type = wanted_type->data.structure.fields[i].type_entry;
assert(field_val->type);
init_const_undefined(g, field_val);
- ConstParent *parent = get_const_val_parent(g, field_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdStruct;
- parent->data.p_struct.struct_val = const_val;
- parent->data.p_struct.field_index = i;
- }
+ field_val->parent.id = ConstParentIdStruct;
+ field_val->parent.data.p_struct.struct_val = const_val;
+ field_val->parent.data.p_struct.field_index = i;
}
} else {
const_val->special = ConstValSpecialUndef;
@@ -5842,11 +5839,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
zig_unreachable();
}
-// Deprecated. Reference the parent field directly.
-ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
- return &value->parent;
-}
-
static const ZigTypeId all_type_ids[] = {
ZigTypeIdMetaType,
ZigTypeIdVoid,
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 8d78ef86e2..a6ad92110e 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -180,7 +180,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
ConstExprValue *create_const_vals(size_t count);
ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
-ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index e12f89756d..2e430a60e0 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3873,8 +3873,20 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
TypeUnionField *field = instruction->field;
- if (!type_has_bits(field->type_entry))
+ if (!type_has_bits(field->type_entry)) {
+ if (union_type->data.unionation.gen_tag_index == SIZE_MAX) {
+ return nullptr;
+ }
+ if (instruction->initializing) {
+ LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
+ LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
+ union_type->data.unionation.gen_tag_index, "");
+ LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
+ &field->enum_field->value);
+ gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
+ }
return nullptr;
+ }
LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0);
diff --git a/src/ir.cpp b/src/ir.cpp
index 32e3692afd..2991dd5186 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17425,11 +17425,9 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
field_val->special = ConstValSpecialUndef;
field_val->type = struct_type->data.structure.fields[i].type_entry;
- ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
- assert(parent != nullptr);
- parent->id = ConstParentIdStruct;
- parent->data.p_struct.struct_val = struct_val;
- parent->data.p_struct.field_index = i;
+ field_val->parent.id = ConstParentIdStruct;
+ field_val->parent.data.p_struct.struct_val = struct_val;
+ field_val->parent.data.p_struct.field_index = i;
}
}
IrInstruction *result;
@@ -17507,11 +17505,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
ConstExprValue *payload_val = create_const_vals(1);
payload_val->special = ConstValSpecialUndef;
payload_val->type = field->type_entry;
- ConstParent *parent = get_const_val_parent(ira->codegen, payload_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdUnion;
- parent->data.p_union.union_val = union_val;
- }
+ payload_val->parent.id = ConstParentIdUnion;
+ payload_val->parent.data.p_union.union_val = union_val;
union_val->special = ConstValSpecialStatic;
bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
@@ -25289,7 +25284,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdReturnPtr:
case IrInstructionIdTypeOf:
case IrInstructionIdStructFieldPtr:
- case IrInstructionIdUnionFieldPtr:
case IrInstructionIdArrayType:
case IrInstructionIdPromiseType:
case IrInstructionIdSliceType:
@@ -25389,6 +25383,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
}
case IrInstructionIdUnwrapErrCode:
return reinterpret_cast(instruction)->initializing;
+ case IrInstructionIdUnionFieldPtr:
+ return reinterpret_cast(instruction)->initializing;
case IrInstructionIdErrWrapPayload:
return reinterpret_cast(instruction)->result_loc != nullptr;
case IrInstructionIdErrWrapCode:
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index 29b70d0a6e..a004089fec 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,4 +1,4 @@
-// TODO remove `use` keyword eventually
+// TODO remove `use` keyword eventually: https://github.com/ziglang/zig/issues/2591
test "zig fmt: change use to usingnamespace" {
try testTransform(
\\use @import("std");
@@ -105,7 +105,6 @@ test "zig fmt: linksection" {
}
test "zig fmt: correctly move doc comments on struct fields" {
- if (true) return error.SkipZigTest; // TODO
try testTransform(
\\pub const section_64 = extern struct {
\\ sectname: [16]u8, /// name of this section
@@ -917,7 +916,6 @@ test "zig fmt: statements with empty line between" {
}
test "zig fmt: ptr deref operator and unwrap optional operator" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\const a = b.*;
\\const a = b.?;
@@ -1020,7 +1018,6 @@ test "zig fmt: same-line comment after a statement" {
}
test "zig fmt: same-line comment after var decl in struct" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\pub const vfs_cap_data = extern struct {
\\ const Data = struct {}; // when on disk.
@@ -1030,7 +1027,6 @@ test "zig fmt: same-line comment after var decl in struct" {
}
test "zig fmt: same-line comment after field decl" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\pub const dirent = extern struct {
\\ d_name: u8,
@@ -1106,7 +1102,6 @@ test "zig fmt: line comments in struct initializer" {
}
test "zig fmt: first line comment in struct initializer" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\pub async fn acquire(self: *Self) HeldLock {
\\ return HeldLock{
@@ -1120,7 +1115,6 @@ test "zig fmt: first line comment in struct initializer" {
}
test "zig fmt: doc comments before struct field" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\pub const Allocator = struct {
\\ /// Allocate byte_count bytes and return them in a slice, with the
@@ -1218,7 +1212,6 @@ test "zig fmt: comments before switch prong" {
}
test "zig fmt: comments before var decl in struct" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\pub const vfs_cap_data = extern struct {
\\ // All of these are mandated as little endian
@@ -1609,7 +1602,6 @@ test "zig fmt: indexing" {
}
test "zig fmt: struct declaration" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\const S = struct {
\\ const Self = @This();
@@ -1641,7 +1633,6 @@ test "zig fmt: struct declaration" {
}
test "zig fmt: enum declaration" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\const E = enum {
\\ Ok,
@@ -1670,7 +1661,6 @@ test "zig fmt: enum declaration" {
}
test "zig fmt: union declaration" {
- if (true) return error.SkipZigTest; // TODO
try testCanonical(
\\const U = union {
\\ Int: u8,
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
index 0e8e9f4eda..410b7e9615 100644
--- a/test/stage1/behavior/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -402,3 +402,23 @@ test "comptime union field value equality" {
expect(a0 != a1);
expect(b0 != b1);
}
+
+test "return union init with void payload" {
+ const S = struct {
+ fn entry() void {
+ expect(func().state == State.one);
+ }
+ const Outer = union(enum) {
+ state: State,
+ };
+ const State = union(enum) {
+ one: void,
+ two: u32,
+ };
+ fn func() Outer {
+ return Outer{ .state = State{ .one = {} }};
+ }
+ };
+ S.entry();
+ comptime S.entry();
+}
--
cgit v1.2.3
From 33f996bb163568c9bb10e5044ed9df53599a917f Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Jun 2019 14:00:44 -0400
Subject: all tests passing on linux
---
doc/langref.html.in | 2 +-
src/all_types.hpp | 5 +++--
src/codegen.cpp | 4 +++-
src/ir.cpp | 4 +++-
std/event/lock.zig | 3 +--
5 files changed, 11 insertions(+), 7 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/doc/langref.html.in b/doc/langref.html.in
index a8673a3d77..92c1aeba8e 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -5096,7 +5096,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
For example, if we were to introduce another function to the above snippet:
- {#code_begin|test_err|values of type 'type' must be comptime known#}
+ {#code_begin|test_err|cannot store runtime value in type 'type'#}
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 5b75d9f96a..4be6f57593 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -335,8 +335,9 @@ struct ConstExprValue {
RuntimeHintSlice rh_slice;
} data;
- ConstExprValue(const ConstExprValue &other) = delete; // plz zero initialize with {}
- ConstExprValue& operator= (const ConstExprValue &other) = delete; // use copy_const_val
+ // uncomment these to find bugs. can't leave them uncommented because of a gcc-9 warning
+ //ConstExprValue(const ConstExprValue &other) = delete; // plz zero initialize with {}
+ //ConstExprValue& operator= (const ConstExprValue &other) = delete; // use copy_const_val
};
enum ReturnKnowledge {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2e430a60e0..0942c671ff 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -691,7 +691,9 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
is_definition, scope_line, flags, is_optimized, nullptr);
scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
- ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);
+ if (!g->strip_debug_symbols) {
+ ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);
+ }
return scope->di_scope;
}
case ScopeIdDecls:
diff --git a/src/ir.cpp b/src/ir.cpp
index 794d41ce22..480493d2ce 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -10726,6 +10726,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
} else if (prev_inst->value.type->id == ZigTypeIdOptional) {
return prev_inst->value.type;
} else {
+ if ((err = type_resolve(ira->codegen, prev_inst->value.type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
return get_optional_type(ira->codegen, prev_inst->value.type);
}
} else {
@@ -21547,7 +21549,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
dest_slice_type, nullptr, true, false);
- if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
+ if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
return result_loc;
}
diff --git a/std/event/lock.zig b/std/event/lock.zig
index 6e7a2bbda7..6c2b29b813 100644
--- a/std/event/lock.zig
+++ b/std/event/lock.zig
@@ -123,8 +123,7 @@ pub const Lock = struct {
};
test "std.event.Lock" {
- // https://github.com/ziglang/zig/issues/2377
- //if (true) return error.SkipZigTest;
+ if (builtin.single_threaded) return error.SkipZigTest;
const allocator = std.heap.direct_allocator;
--
cgit v1.2.3
From 517bdea7549453d958c31cf2af5dc298ea5508a9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Jun 2019 16:27:24 -0400
Subject: fix incorrectly omitting variable declarations
in non-debug modes
---
src/codegen.cpp | 3 ---
1 file changed, 3 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 7601008e16..8842e161cc 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3373,9 +3373,6 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrI
if (!type_has_bits(var->var_type))
return nullptr;
- if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
- return nullptr;
-
var->value_ref = ir_llvm_value(g, instruction->var_ptr);
gen_var_debug_decl(g, var);
return nullptr;
--
cgit v1.2.3
From 69c7c5de09e16e96a6ea5207ef8b3a21e9d119f9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 27 Jun 2019 19:15:33 -0400
Subject: fixups
* better detection for already seen packages
* "root" instead of "@root"
---
src/all_types.hpp | 2 ++
src/codegen.cpp | 30 ++++++++++++++----------------
std/special/bootstrap.zig | 5 ++---
3 files changed, 18 insertions(+), 19 deletions(-)
(limited to 'src/codegen.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 774a00fdb7..bb5bef04bb 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1110,6 +1110,8 @@ struct ZigPackage {
// reminder: hash tables must be initialized before use
HashMap package_table;
+
+ bool added_to_cache;
};
// Stuff that only applies to a struct which is the implicit root struct of a file
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 1a01e135d2..6ad779fd24 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -180,7 +180,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
g->root_package = new_package(".", "", "");
}
- g->root_package->package_table.put(buf_create_from_str("@root"), g->root_package);
+ g->root_package->package_table.put(buf_create_from_str("root"), g->root_package);
g->zig_std_special_dir = buf_alloc();
os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
@@ -8055,6 +8055,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
+ g->std_package->package_table.put(buf_create_from_str("root"),
+ g->is_test_build ? g->test_runner_package : g->root_package);
g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,
SourceKindPkgMain);
@@ -8522,8 +8524,10 @@ static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *ba
return add_source_file(g, package, resolved_path, import_code, SourceKindPkgMain);
}
-static ZigPackage *create_bootstrap_pkg(CodeGen *g) {
- return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");
+static ZigPackage *create_bootstrap_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
+ ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");
+ package->package_table.put(buf_create_from_str("root"), pkg_with_main);
+ return package;
}
static ZigPackage *create_test_runner_pkg(CodeGen *g) {
@@ -8647,12 +8651,12 @@ static void gen_root_source(CodeGen *g) {
!g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
{
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
+ g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
}
if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup &&
g->out_type == OutTypeLib && g->is_dynamic)
{
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap_lib.zig");
+ g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
}
if (!g->error_during_imports) {
@@ -8660,7 +8664,7 @@ static void gen_root_source(CodeGen *g) {
}
if (g->is_test_build) {
create_test_compile_var_and_add_test_runner(g);
- g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
+ g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->test_runner_package), "bootstrap.zig");
if (!g->error_during_imports) {
semantic_analyze(g);
@@ -9375,6 +9379,7 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
if (buf_len(&pkg->root_src_path) == 0)
return;
+ pkg->added_to_cache = true;
Buf *rel_full_path = buf_alloc();
os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path);
@@ -9386,11 +9391,7 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
if (!entry)
break;
- // TODO: I think we need a more sophisticated detection of
- // packages we have already seen
- if (entry->value != pkg) {
- auto root = pkg->package_table.maybe_get(buf_create_from_str("@root"));
- if (root != nullptr && entry->value == root->value) continue;
+ if (!pkg->added_to_cache) {
cache_buf(ch, entry->key);
add_cache_pkg(g, ch, entry->value);
}
@@ -9648,11 +9649,8 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
assert(g->compile_var_package != nullptr);
pkg->package_table.put(buf_create_from_str("std"), g->std_package);
- if (g->is_test_build) {
- pkg->package_table.put(buf_create_from_str("@root"), g->test_runner_package);
- } else {
- pkg->package_table.put(buf_create_from_str("@root"), g->root_package);
- }
+ ZigPackage *main_pkg = g->is_test_build ? g->test_runner_package : g->root_package;
+ pkg->package_table.put(buf_create_from_str("root"), main_pkg);
pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
}
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index f1286bd659..7177f58b8a 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -1,7 +1,6 @@
-// This file is in a package which has the root source file exposed as "@root".
-// It is included in the compilation unit when exporting an executable.
+// This file is included in the compilation unit when exporting an executable.
-const root = @import("@root");
+const root = @import("root");
const std = @import("std");
const builtin = @import("builtin");
const assert = std.debug.assert;
--
cgit v1.2.3