From c19bdc2d370f3a72ef492e2f4e6264e2a0dd91ec Mon Sep 17 00:00:00 2001
From: Shawn Landden
Date: Mon, 6 May 2019 11:41:15 -0500
Subject: stage1: add @hasField() built-in
This was quite straight-forward
Closes: #1439
---
src/ir_print.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
(limited to 'src/ir_print.cpp')
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index dba0e4ee00..683bf0dd86 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1107,6 +1107,14 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction)
fprintf(irp->f, ")");
}
+static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) {
+ fprintf(irp->f, "@hasField(");
+ ir_print_other_instruction(irp, instruction->container_type);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->field_name_expr);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) {
fprintf(irp->f, "@typeId(");
ir_print_other_instruction(irp, instruction->type_value);
@@ -1757,6 +1765,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTypeInfo:
ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
break;
+ case IrInstructionIdHasField:
+ ir_print_has_field(irp, (IrInstructionHasField *)instruction);
+ break;
case IrInstructionIdTypeId:
ir_print_type_id(irp, (IrInstructionTypeId *)instruction);
break;
--
cgit v1.2.3
From 9b7ad124810e4a3df964927ace449502daa167f9 Mon Sep 17 00:00:00 2001
From: Robert Scott
Date: Thu, 9 May 2019 02:28:14 -0700
Subject: Implement @unionInit
---
src/all_types.hpp | 13 ++++++
src/codegen.cpp | 2 +
src/ir.cpp | 90 ++++++++++++++++++++++++++++++++++++++----
src/ir_print.cpp | 14 +++++++
test/stage1/behavior/union.zig | 37 ++++++++++++++++-
5 files changed, 148 insertions(+), 8 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 3b6ac32ea5..2dd70f64f1 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1471,6 +1471,7 @@ enum BuiltinFnId {
BuiltinFnIdErrorReturnTrace,
BuiltinFnIdAtomicRmw,
BuiltinFnIdAtomicLoad,
+ BuiltinFnIdUnionInit,
};
struct BuiltinFnEntry {
@@ -2297,6 +2298,7 @@ enum IrInstructionId {
IrInstructionIdArrayToVector,
IrInstructionIdAssertZero,
IrInstructionIdAssertNonNull,
+ IrInstructionIdUnionInit2,
};
struct IrInstruction {
@@ -3503,6 +3505,17 @@ struct IrInstructionAssertNonNull {
IrInstruction *target;
};
+// TODO, need a better name. Using 2 because there is currently a IrInstructionUnionInit
+// It seems like the first one should only be used during the analyze phase, but still
+// don't understand it all.
+struct IrInstructionUnionInit2 {
+ IrInstruction base;
+
+ IrInstruction *union_type_value;
+ IrInstruction *field_name_expr;
+ IrInstruction *value;
+};
+
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 3a34894bb3..39a8c194ac 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5616,6 +5616,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdLoadPtr:
case IrInstructionIdBitCast:
case IrInstructionIdGlobalAsm:
+ case IrInstructionIdUnionInit2:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -7409,6 +7410,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
+ create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);
}
static const char *bool_to_str(bool b) {
diff --git a/src/ir.cpp b/src/ir.cpp
index 2d81f0c219..643f6845c6 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -188,7 +188,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
assert(get_src_ptr_type(const_val->type) != nullptr);
assert(const_val->special == ConstValSpecialStatic);
ConstExprValue *result;
-
+
switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
case OnePossibleValueInvalid:
zig_unreachable();
@@ -200,7 +200,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
case OnePossibleValueNo:
break;
}
-
+
switch (const_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
@@ -1011,6 +1011,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *)
return IrInstructionIdAssertNonNull;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit2 *) {
+ return IrInstructionIdUnionInit2;
+}
+
template
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate(1);
@@ -1312,6 +1316,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
return &instruction->base;
}
+
static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
@@ -3025,6 +3030,21 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
+static IrInstruction *ir_build_union_init_2(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type_value, IrInstruction *field_name_expr, IrInstruction *value) {
+ IrInstructionUnionInit2 *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->union_type_value = union_type_value;
+ instruction->field_name_expr = field_name_expr;
+ instruction->value = value;
+
+ ir_ref_instruction(union_type_value, irb->current_basic_block);
+ ir_ref_instruction(field_name_expr, irb->current_basic_block);
+ ir_ref_instruction(value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+
static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
IrInstruction *vector, ZigType *result_type)
{
@@ -3868,7 +3888,7 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode
TldVar *tld_var = allocate(1);
init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);
tld_var->base.resolution = TldResolutionInvalid;
- tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
+ tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
&g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid);
scope_decls->decl_table.put(var_name, &tld_var->base);
}
@@ -5098,6 +5118,29 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
return ir_lval_wrap(irb, scope, result, lval);
}
+ case BuiltinFnIdUnionInit:
+ {
+
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
+ if (arg0_value == irb->codegen->invalid_instruction)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
+ if (arg1_value == irb->codegen->invalid_instruction)
+ return arg1_value;
+
+ AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
+ IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
+ if (arg2_value == irb->codegen->invalid_instruction)
+ return arg2_value;
+
+ IrInstruction *result = ir_build_union_init_2(irb, scope, node, arg0_value, arg1_value, arg2_value);
+
+ // TODO: Not sure if we need ir_lval_wrap or not.
+ return result;
+ }
}
zig_unreachable();
}
@@ -6328,7 +6371,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
prong_values, prong_values_len);
var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);
} else {
- var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node,
+ 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
@@ -12372,7 +12415,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
} else {
return is_non_null;
}
- } else if (is_equality_cmp &&
+ } else if (is_equality_cmp &&
((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&
op2->value.type->data.pointer.ptr_len == PtrLenC) ||
(op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&
@@ -19383,7 +19426,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err)));
return ira->codegen->invalid_instruction;
}
-
+
if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) {
ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err)));
return ira->codegen->invalid_instruction;
@@ -20333,7 +20376,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
return ira->codegen->invalid_instruction;
// TODO test this at comptime with u8 and non-u8 types
- // TODO test with dest ptr being a global runtime variable
+ // TODO test with dest ptr being a global runtime variable
if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
casted_src_ptr->value.special == ConstValSpecialStatic &&
casted_count->value.special == ConstValSpecialStatic &&
@@ -23151,6 +23194,35 @@ static IrInstruction *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira,
return ir_const_void(ira, &instruction->base);
}
+static IrInstruction *ir_analyze_instruction_union_init_2(IrAnalyze *ira, IrInstructionUnionInit2 *union_init_instruction)
+{
+ Error err;
+ IrInstruction *union_type_value = union_init_instruction->union_type_value->child;
+ ZigType *union_type = ir_resolve_type(ira, union_type_value);
+ if (type_is_invalid(union_type)) {
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (union_type->id != ZigTypeIdUnion)
+ return ira->codegen->invalid_instruction;
+
+ if ((err = ensure_complete_type(ira->codegen, union_type)))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *field_name_expr = union_init_instruction->field_name_expr->child;
+ Buf *field_name = ir_resolve_str(ira, field_name_expr);
+ if (!field_name)
+ return ira->codegen->invalid_instruction;
+
+ IrInstructionContainerInitFieldsField *fields = allocate(1);
+
+ fields[0].name = field_name;
+ fields[0].value = union_init_instruction->value;
+ fields[0].source_node = union_init_instruction->base.source_node;
+
+ return ir_analyze_container_init_fields_union(ira, &union_init_instruction->base, union_type, 1, fields);
+}
+
static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -23445,6 +23517,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction);
case IrInstructionIdCheckRuntimeScope:
return ir_analyze_instruction_check_runtime_scope(ira, (IrInstructionCheckRuntimeScope *)instruction);
+ case IrInstructionIdUnionInit2:
+ return ir_analyze_instruction_union_init_2(ira, (IrInstructionUnionInit2 *)instruction);
}
zig_unreachable();
}
@@ -23681,6 +23755,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdEnumToInt:
case IrInstructionIdVectorToArray:
case IrInstructionIdArrayToVector:
+ case IrInstructionIdUnionInit2:
+
return false;
case IrInstructionIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index d38b552749..6d98580d02 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1453,6 +1453,17 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va
}
}
+
+static void ir_print_uniont_init_2(IrPrint *irp, IrInstructionUnionInit2 *instruction) {
+ fprintf(irp->f, "@unionInit(");
+ ir_print_other_instruction(irp, instruction->union_type_value);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->field_name_expr);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->value);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1920,6 +1931,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdResizeSlice:
ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
break;
+ case IrInstructionIdUnionInit2:
+ ir_print_uniont_init_2(irp, (IrInstructionUnionInit2 *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
index b8bb9a51b8..be96b659f6 100644
--- a/test/stage1/behavior/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -374,7 +374,7 @@ const Attribute = union(enum) {
fn setAttribute(attr: Attribute) void {}
fn Setter(attr: Attribute) type {
- return struct{
+ return struct {
fn set() void {
setAttribute(attr);
}
@@ -402,3 +402,38 @@ test "comptime union field value equality" {
expect(a0 != a1);
expect(b0 != b1);
}
+
+test "unionInit can modify a union type" {
+ const UnionInitEnum = union(enum) {
+ Boolean: bool,
+ Byte: u8,
+ };
+
+ var value: UnionInitEnum = undefined;
+
+ value = @unionInit(UnionInitEnum, "Boolean", true);
+ expect(value.Boolean == true);
+ value.Boolean = false;
+ expect(value.Boolean == false);
+
+ value = @unionInit(UnionInitEnum, "Byte", 2);
+ expect(value.Byte == 2);
+ value.Byte = 3;
+ expect(value.Byte == 3);
+}
+
+test "unionInit can modify a pointer value" {
+ const UnionInitEnum = union(enum) {
+ Boolean: bool,
+ Byte: u8,
+ };
+
+ var value: UnionInitEnum = undefined;
+ var value_ptr = &value;
+
+ value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true);
+ expect(value.Boolean == true);
+
+ value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);
+ expect(value.Byte == 2);
+}
--
cgit v1.2.3
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
}
```
---
BRANCH_TODO | 10 ++
CMakeLists.txt | 1 +
src/all_types.hpp | 82 ++++++++++-
src/codegen.cpp | 90 +++++++-----
src/ir.cpp | 401 ++++++++++++++++++++++++++++++++++++++++--------------
src/ir_print.cpp | 88 +++++++++++-
6 files changed, 521 insertions(+), 151 deletions(-)
create mode 100644 BRANCH_TODO
(limited to 'src/ir_print.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
new file mode 100644
index 0000000000..294d3e677f
--- /dev/null
+++ b/BRANCH_TODO
@@ -0,0 +1,10 @@
+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
+
+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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ff4cebf40..8e4b8e8c0b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6728,6 +6728,7 @@ add_custom_command(
"-Doutput-dir=${CMAKE_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
DEPENDS
+ zig0
"${CMAKE_SOURCE_DIR}/src-self-hosted/dep_tokenizer.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 2a6bb1feb5..ae8d9c3fb8 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -34,12 +34,14 @@ struct CodeGen;
struct ConstExprValue;
struct IrInstruction;
struct IrInstructionCast;
+struct IrInstructionAllocaGen;
struct IrBasicBlock;
struct ScopeDecls;
struct ZigWindowsSDK;
struct Tld;
struct TldExport;
struct IrAnalyze;
+struct ResultLoc;
enum X64CABIClass {
X64CABIClass_Unknown,
@@ -1359,6 +1361,7 @@ struct ZigFn {
AstNode *fn_static_eval_set_node;
ZigList alloca_list;
+ ZigList alloca_gen_list;
ZigList variable_list;
Buf *section_name;
@@ -2171,7 +2174,9 @@ enum IrInstructionId {
IrInstructionIdUnionFieldPtr,
IrInstructionIdElemPtr,
IrInstructionIdVarPtr,
- IrInstructionIdCall,
+ IrInstructionIdReturnPtr,
+ IrInstructionIdCallSrc,
+ IrInstructionIdCallGen,
IrInstructionIdConst,
IrInstructionIdReturn,
IrInstructionIdCast,
@@ -2308,6 +2313,8 @@ enum IrInstructionId {
IrInstructionIdAssertNonNull,
IrInstructionIdHasDecl,
IrInstructionIdUndeclaredIdent,
+ IrInstructionIdAllocaSrc,
+ IrInstructionIdAllocaGen,
};
struct IrInstruction {
@@ -2335,14 +2342,14 @@ struct IrInstructionDeclVarSrc {
ZigVar *var;
IrInstruction *var_type;
IrInstruction *align_value;
- IrInstruction *init_value;
+ IrInstruction *ptr;
};
struct IrInstructionDeclVarGen {
IrInstruction base;
ZigVar *var;
- IrInstruction *init_value;
+ IrInstruction *var_ptr;
};
struct IrInstructionCondBr {
@@ -2528,14 +2535,21 @@ struct IrInstructionVarPtr {
ScopeFnDef *crossed_fndef_scope;
};
-struct IrInstructionCall {
+// For functions that have a return type for which handle_is_ptr is true, a
+// result location pointer is the secret first parameter ("sret"). This
+// instruction returns that pointer.
+struct IrInstructionReturnPtr {
+ IrInstruction base;
+};
+
+struct IrInstructionCallSrc {
IrInstruction base;
IrInstruction *fn_ref;
ZigFn *fn_entry;
size_t arg_count;
IrInstruction **args;
- LLVMValueRef tmp_ptr;
+ ResultLoc *result_loc;
IrInstruction *async_allocator;
IrInstruction *new_stack;
@@ -2544,6 +2558,21 @@ struct IrInstructionCall {
bool is_comptime;
};
+struct IrInstructionCallGen {
+ IrInstruction base;
+
+ IrInstruction *fn_ref;
+ ZigFn *fn_entry;
+ size_t arg_count;
+ IrInstruction **args;
+ IrInstruction *result_loc;
+
+ IrInstruction *async_allocator;
+ IrInstruction *new_stack;
+ FnInline fn_inline;
+ bool is_async;
+};
+
struct IrInstructionConst {
IrInstruction base;
};
@@ -3527,6 +3556,47 @@ struct IrInstructionUndeclaredIdent {
Buf *name;
};
+struct IrInstructionAllocaSrc {
+ IrInstruction base;
+
+ IrInstruction *align;
+ IrInstruction *is_comptime;
+ const char *name_hint;
+};
+
+struct IrInstructionAllocaGen {
+ IrInstruction base;
+
+ uint32_t align;
+ const char *name_hint;
+};
+
+enum ResultLocId {
+ ResultLocIdInvalid,
+ ResultLocIdNone,
+ ResultLocIdVar,
+ ResultLocIdReturn,
+};
+
+struct ResultLoc {
+ ResultLocId id;
+ IrInstruction *source_instruction;
+};
+
+struct ResultLocNone {
+ ResultLoc base;
+};
+
+struct ResultLocVar {
+ ResultLoc base;
+
+ ZigVar *var;
+};
+
+struct ResultLocReturn {
+ ResultLoc base;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
@@ -3574,7 +3644,7 @@ struct FnWalkAttrs {
struct FnWalkCall {
ZigList *gen_param_values;
- IrInstructionCall *inst;
+ IrInstructionCallGen *inst;
bool is_var_args;
};
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);
diff --git a/src/ir.cpp b/src/ir.cpp
index fb9e7b51c7..5b6ce22620 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -157,7 +157,8 @@ 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);
+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);
@@ -475,8 +476,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) {
return IrInstructionIdVarPtr;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {
- return IrInstructionIdCall;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnPtr *) {
+ return IrInstructionIdReturnPtr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {
+ return IrInstructionIdCallSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {
+ return IrInstructionIdCallGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {
@@ -1019,6 +1028,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent
return IrInstructionIdUndeclaredIdent;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaSrc *) {
+ return IrInstructionIdAllocaSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaGen *) {
+ return IrInstructionIdAllocaGen;
+}
+
template
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate(1);
@@ -1254,6 +1271,13 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so
return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr);
}
+static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
+ IrInstructionReturnPtr *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ty;
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr,
IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len)
{
@@ -1320,12 +1344,12 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
return &instruction->base;
}
-static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
+static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
- IrInstruction *new_stack)
+ IrInstruction *new_stack, ResultLoc *result_loc)
{
- IrInstructionCall *call_instruction = ir_build_instruction(irb, scope, source_node);
+ IrInstructionCallSrc *call_instruction = ir_build_instruction(irb, scope, source_node);
call_instruction->fn_entry = fn_entry;
call_instruction->fn_ref = fn_ref;
call_instruction->is_comptime = is_comptime;
@@ -1335,6 +1359,7 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
call_instruction->is_async = is_async;
call_instruction->async_allocator = async_allocator;
call_instruction->new_stack = new_stack;
+ call_instruction->result_loc = result_loc;
if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
for (size_t i = 0; i < arg_count; i += 1)
@@ -1345,6 +1370,33 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
return &call_instruction->base;
}
+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)
+{
+ IrInstructionCallGen *call_instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ call_instruction->fn_entry = fn_entry;
+ call_instruction->fn_ref = fn_ref;
+ call_instruction->fn_inline = fn_inline;
+ call_instruction->args = args;
+ call_instruction->arg_count = arg_count;
+ call_instruction->is_async = is_async;
+ call_instruction->async_allocator = async_allocator;
+ call_instruction->new_stack = new_stack;
+ call_instruction->result_loc = 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)
+ 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);
+
+ return &call_instruction->base;
+}
+
static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source_node,
size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
{
@@ -1511,7 +1563,7 @@ 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 *init_value)
+ ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *ptr)
{
IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction(irb, scope, source_node);
decl_var_instruction->base.value.special = ConstValSpecialStatic;
@@ -1519,26 +1571,26 @@ static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNod
decl_var_instruction->var = var;
decl_var_instruction->var_type = var_type;
decl_var_instruction->align_value = align_value;
- decl_var_instruction->init_value = init_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(init_value, irb->current_basic_block);
+ ir_ref_instruction(ptr, irb->current_basic_block);
return &decl_var_instruction->base;
}
static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
- ZigVar *var, IrInstruction *init_value)
+ ZigVar *var, IrInstruction *var_ptr)
{
IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
decl_var_instruction->base.value.special = ConstValSpecialStatic;
decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
decl_var_instruction->var = var;
- decl_var_instruction->init_value = init_value;
+ decl_var_instruction->var_ptr = var_ptr;
- ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
+ ir_ref_instruction(var_ptr, ira->new_irb.current_basic_block);
return &decl_var_instruction->base;
}
@@ -3109,6 +3161,32 @@ static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *so
return &instruction->base;
}
+static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *align, const char *name_hint, IrInstruction *is_comptime)
+{
+ IrInstructionAllocaSrc *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->base.is_gen = true;
+ instruction->align = align;
+ instruction->name_hint = name_hint;
+ instruction->is_comptime = is_comptime;
+
+ if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block);
+ if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstructionAllocaGen *ir_create_alloca_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ uint32_t align, const char *name_hint)
+{
+ IrInstructionAllocaGen *instruction = ir_create_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->align = align;
+ instruction->name_hint = name_hint;
+
+ return instruction;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -3321,12 +3399,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
switch (node->data.return_expr.kind) {
case ReturnKindUnconditional:
{
+ ResultLocReturn *result_loc_ret = allocate(1);
+ result_loc_ret->base.id = ResultLocIdReturn;
+
IrInstruction *return_value;
if (expr_node) {
// Temporarily set this so that if we return a type it gets the name of the function
ZigFn *prev_name_fn = irb->exec->name_fn;
irb->exec->name_fn = exec_fn_entry(irb->exec);
- return_value = ir_gen_node(irb, expr_node, scope);
+ return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base);
irb->exec->name_fn = prev_name_fn;
if (return_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -3373,17 +3454,21 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
- return ir_gen_async_return(irb, scope, node, return_value, false);
+ IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);
+ result_loc_ret->base.source_instruction = result;
+ return result;
} else {
// generate unconditional defers
ir_gen_defers_for_block(irb, scope, outer_scope, false);
- return ir_gen_async_return(irb, scope, node, return_value, false);
+ IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);
+ result_loc_ret->base.source_instruction = result;
+ return result;
}
}
case ReturnKindError:
{
assert(expr_node);
- IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ 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);
@@ -3592,7 +3677,7 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no
}
static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
- IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr);
+ IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction)
@@ -3603,7 +3688,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)
}
static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
- IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr);
+ IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
if (lvalue == irb->codegen->invalid_instruction)
return lvalue;
IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
@@ -3705,7 +3790,7 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
AstNode *op1_node = node->data.bin_op_expr.op1;
AstNode *op2_node = node->data.bin_op_expr.op2;
- IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr);
+ IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr);
if (maybe_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -3968,7 +4053,7 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode
assert(node->type == NodeTypeArrayAccessExpr);
AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
- IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr);
+ IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr);
if (array_ref_instruction == irb->codegen->invalid_instruction)
return array_ref_instruction;
@@ -3991,7 +4076,7 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode
AstNode *container_ref_node = node->data.field_access_expr.struct_expr;
Buf *field_name = node->data.field_access_expr.field_name;
- IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr);
+ IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr);
if (container_ref_instruction == irb->codegen->invalid_instruction)
return container_ref_instruction;
@@ -4041,7 +4126,9 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no
zig_unreachable();
}
-static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeFnCallExpr);
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
@@ -4625,7 +4712,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
case BuiltinFnIdField:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr);
+ IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
@@ -4855,7 +4942,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
- IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr, nullptr);
+ 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);
}
case BuiltinFnIdNewStackCall:
@@ -4885,7 +4973,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return args[i];
}
- IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, false, nullptr, new_stack);
+ 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);
}
case BuiltinFnIdTypeId:
@@ -5148,11 +5237,13 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
zig_unreachable();
}
-static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
+static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
+ ResultLoc *result_loc)
+{
assert(node->type == NodeTypeFnCallExpr);
if (node->data.fn_call_expr.is_builtin)
- return ir_gen_builtin_fn_call(irb, scope, node, lval);
+ return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
@@ -5178,8 +5269,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
}
}
- IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
- is_async, async_allocator, nullptr);
+ 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);
}
@@ -5244,7 +5335,7 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast
assert(node->type == NodeTypePrefixOpExpr);
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
- IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
+ IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
if (value == irb->codegen->invalid_instruction)
return value;
@@ -5339,7 +5430,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
LVal lval)
{
- IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ 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;
@@ -5384,7 +5475,7 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval);
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), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval);
}
}
zig_unreachable();
@@ -5486,17 +5577,27 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
// Parser should ensure that this never happens
assert(variable_declaration->threadlocal_tok == nullptr);
+ IrInstruction *alloca = ir_build_alloca_src(irb, scope, node, align_value,
+ 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;
+
// 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(irb, variable_declaration->expr, scope);
+ IrInstruction *init_value = ir_gen_node_extra(irb, variable_declaration->expr, scope, LValNone,
+ &result_loc_var->base);
irb->exec->name = old_exec_name;
if (init_value == irb->codegen->invalid_instruction)
return init_value;
- return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
+ return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, alloca);
}
static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -5534,7 +5635,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
} else {
payload_scope = subexpr_scope;
}
- IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr);
+ IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
+ 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);
@@ -5621,7 +5723,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol,
true, false, false, is_comptime);
Scope *child_scope = payload_var->child_scope;
- IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr);
+ IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
+ LValPtr, nullptr);
if (maybe_val_ptr == irb->codegen->invalid_instruction)
return maybe_val_ptr;
IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr);
@@ -5775,7 +5878,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
}
assert(elem_node->type == NodeTypeSymbol);
- IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr);
+ IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr, nullptr);
if (array_val_ptr == irb->codegen->invalid_instruction)
return array_val_ptr;
@@ -6182,7 +6285,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
AstNode *else_node = node->data.test_expr.else_node;
bool var_is_ptr = node->data.test_expr.var_is_ptr;
- IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (maybe_val_ptr == irb->codegen->invalid_instruction)
return maybe_val_ptr;
@@ -6261,7 +6364,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
Buf *var_symbol = node->data.if_err_expr.var_symbol;
Buf *err_symbol = node->data.if_err_expr.err_symbol;
- IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr);
+ IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr);
if (err_val_ptr == irb->codegen->invalid_instruction)
return err_val_ptr;
@@ -6397,7 +6500,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
assert(node->type == NodeTypeSwitchExpr);
AstNode *target_node = node->data.switch_expr.expr;
- IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr);
+ IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr);
if (target_value_ptr == irb->codegen->invalid_instruction)
return target_value_ptr;
IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr);
@@ -6597,7 +6700,7 @@ static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNo
assert(node->type == NodeTypeCompTime);
Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope);
- return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);
+ return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
}
static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
@@ -6776,7 +6879,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
AstNode *start_node = slice_expr->start;
AstNode *end_node = slice_expr->end;
- IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr);
+ IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr);
if (ptr_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -6814,7 +6917,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
}
- IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr);
+ IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr);
if (err_union_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -7560,7 +7663,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
}
static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
- LVal lval)
+ LVal lval, ResultLoc *result_loc)
{
assert(scope);
switch (node->type) {
@@ -7576,7 +7679,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeBlock:
return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval);
case NodeTypeGroupedExpr:
- return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval);
+ 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);
case NodeTypeIntLiteral:
@@ -7588,7 +7691,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeSymbol:
return ir_gen_symbol(irb, scope, node, lval);
case NodeTypeFnCallExpr:
- return ir_gen_fn_call(irb, scope, node, lval);
+ 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);
case NodeTypePrefixOpExpr:
@@ -7617,7 +7720,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
}
case NodeTypePtrDeref: {
AstNode *expr_node = node->data.ptr_deref_expr.target;
- IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
+ IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
if (value == irb->codegen->invalid_instruction)
return value;
@@ -7629,7 +7732,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeUnwrapOptional: {
AstNode *expr_node = node->data.unwrap_optional.expr;
- IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
+ IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
if (maybe_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
@@ -7697,14 +7800,23 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
zig_unreachable();
}
-static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval) {
- IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval);
+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;
+ }
+ IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);
return result;
}
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {
- return ir_gen_node_extra(irb, node, scope, LValNone);
+ return ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
}
static void invalidate_exec(IrExecutable *exec) {
@@ -7837,7 +7949,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
irb->exec->coro_final_cleanup_block = ir_create_basic_block(irb, scope, "FinalCleanup");
}
- IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone);
+ IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
assert(result);
if (irb->exec->invalid)
return false;
@@ -7946,7 +8058,10 @@ 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
- ir_build_call(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr);
+ 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);
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);
@@ -13641,12 +13756,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
Error err;
ZigVar *var = decl_var_instruction->var;
- IrInstruction *init_value = decl_var_instruction->init_value->child;
- if (type_is_invalid(init_value->value.type)) {
- var->var_type = ira->codegen->builtin_types.entry_invalid;
- return ira->codegen->invalid_instruction;
- }
-
ZigType *explicit_type = nullptr;
IrInstruction *var_type = nullptr;
if (decl_var_instruction->var_type != nullptr) {
@@ -13661,12 +13770,19 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
AstNode *source_node = decl_var_instruction->base.source_node;
- IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
bool is_comptime_var = ir_get_var_is_comptime(var);
bool var_class_requires_const = false;
- ZigType *result_type = casted_init_value->value.type;
+ IrInstruction *var_ptr = decl_var_instruction->ptr->child;
+ if (type_is_invalid(var_ptr->value.type)) {
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
+ }
+
+ assert(var_ptr->value.type->id == ZigTypeIdPointer);
+
+ ZigType *result_type = var_ptr->value.type->data.pointer.child_type;
if (type_is_invalid(result_type)) {
result_type = ira->codegen->builtin_types.entry_invalid;
} else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) {
@@ -13675,6 +13791,14 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
result_type = ira->codegen->builtin_types.entry_invalid;
}
+ ConstExprValue *init_val = nullptr;
+ 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;
+ }
+ }
+
switch (type_requires_comptime(ira->codegen, result_type)) {
case ReqCompTimeInvalid:
result_type = ira->codegen->builtin_types.entry_invalid;
@@ -13689,18 +13813,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
}
break;
case ReqCompTimeNo:
- if (casted_init_value->value.special == ConstValSpecialStatic &&
- casted_init_value->value.type->id == ZigTypeIdFn &&
- casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
- casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
- {
- var_class_requires_const = true;
- if (!var->src_is_const && !is_comptime_var) {
- ErrorMsg *msg = ir_add_error_node(ira, source_node,
- buf_sprintf("functions marked inline must be stored in const or comptime var"));
- AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node;
- add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
- result_type = ira->codegen->builtin_types.entry_invalid;
+ if (init_val != nullptr) {
+ if (init_val->special == ConstValSpecialStatic &&
+ init_val->type->id == ZigTypeIdFn &&
+ init_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
+ init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
+ {
+ var_class_requires_const = true;
+ if (!var->src_is_const && !is_comptime_var) {
+ ErrorMsg *msg = ir_add_error_node(ira, source_node,
+ buf_sprintf("functions marked inline must be stored in const or comptime var"));
+ AstNode *proto_node = init_val->data.x_ptr.data.fn.fn_entry->proto_node;
+ add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
+ result_type = ira->codegen->builtin_types.entry_invalid;
+ }
}
}
break;
@@ -13747,11 +13873,11 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
}
}
- if (casted_init_value->value.special != ConstValSpecialRuntime) {
+ if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {
if (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, &casted_init_value->value, !is_comptime_var || var->gen_is_const);
+ copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);
if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {
return ir_const_void(ira, &decl_var_instruction->base);
@@ -13768,7 +13894,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
if (fn_entry)
fn_entry->variable_list.append(var);
- return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
+ return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, var_ptr);
}
static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) {
@@ -14076,7 +14202,67 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
zig_unreachable();
}
-static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry,
+static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,
+ uint32_t align, const char *name_hint, bool force_comptime)
+{
+ Error err;
+
+ ConstExprValue *pointee = create_const_vals(1);
+ 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.data.x_ptr.special = ConstPtrSpecialRef;
+ result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutRuntimeVar;
+ result->base.value.data.x_ptr.data.ref.pointee = pointee;
+
+ if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
+ return ira->codegen->invalid_instruction;
+ assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);
+
+ pointee->type = var_type;
+ result->base.value.type = get_pointer_to_type_extra(ira->codegen, var_type, false, false,
+ PtrLenSingle, align, 0, 0, false);
+
+ ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ if (fn_entry != nullptr) {
+ fn_entry->alloca_gen_list.append(result);
+ }
+ result->base.is_gen = true;
+ return &result->base;
+}
+
+static IrInstruction *ir_resolve_result_loc(IrAnalyze *ira, ResultLoc *result_loc, ZigType *elem_type) {
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ zig_unreachable();
+ 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
+ IrInstruction *alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, elem_type, align,
+ alloca_src->name_hint, force_comptime);
+ alloca_src->base.child = alloca_gen;
+ }
+ 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);
+ }
+ }
+ zig_unreachable();
+}
+
+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)
{
@@ -14109,8 +14295,10 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
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 = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,
- fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst, nullptr);
+ 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;
}
@@ -14416,7 +14604,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
return result;
}
-static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
+static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
{
@@ -14861,19 +15049,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
if (call_instruction->is_async) {
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
fn_ref, casted_args, impl_param_count, async_allocator_inst);
- ir_add_alloca(ira, result, result->value.type);
return ir_finish_anal(ira, result);
}
assert(async_allocator_inst == nullptr);
- IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,
- call_instruction->base.scope, call_instruction->base.source_node,
- impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
- call_instruction->is_async, nullptr, casted_new_stack);
+ 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;
- ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
-
return ir_finish_anal(ira, new_call_instruction);
}
@@ -14957,7 +15143,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
casted_args, call_param_count, async_allocator_inst);
- ir_add_alloca(ira, result, result->value.type);
return ir_finish_anal(ira, result);
}
@@ -14967,15 +15152,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
return ira->codegen->invalid_instruction;
}
- IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,
- call_instruction->base.scope, call_instruction->base.source_node,
- fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr, casted_new_stack);
+ 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;
- ir_add_alloca(ira, new_call_instruction, return_type);
return ir_finish_anal(ira, new_call_instruction);
}
-static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
+static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {
IrInstruction *fn_ref = call_instruction->fn_ref->child;
if (type_is_invalid(fn_ref->value.type))
return ira->codegen->invalid_instruction;
@@ -23304,6 +23488,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
case IrInstructionIdResizeSlice:
case IrInstructionIdLoadPtrGen:
case IrInstructionIdBitCastGen:
+ case IrInstructionIdCallGen:
+ case IrInstructionIdReturnPtr:
+ case IrInstructionIdAllocaGen:
zig_unreachable();
case IrInstructionIdReturn:
@@ -23326,8 +23513,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);
case IrInstructionIdFieldPtr:
return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);
- case IrInstructionIdCall:
- return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
+ case IrInstructionIdCallSrc:
+ return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);
case IrInstructionIdBr:
return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
case IrInstructionIdCondBr:
@@ -23580,13 +23767,15 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction);
case IrInstructionIdUndeclaredIdent:
return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);
+ case IrInstructionIdAllocaSrc:
+ return nullptr;
}
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, old_instruction);
+ ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
old_instruction->child = new_instruction;
return new_instruction;
}
@@ -23637,13 +23826,15 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
}
IrInstruction *new_instruction = ir_analyze_instruction(ira, old_instruction);
- if (type_is_invalid(new_instruction->value.type) && ir_should_inline(new_exec, old_instruction->scope)) {
- return ira->codegen->builtin_types.entry_invalid;
- }
+ if (new_instruction != nullptr) {
+ if (type_is_invalid(new_instruction->value.type) && ir_should_inline(new_exec, old_instruction->scope)) {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
- // unreachable instructions do their own control flow.
- if (new_instruction->value.type->id == ZigTypeIdUnreachable)
- continue;
+ // unreachable instructions do their own control flow.
+ if (new_instruction->value.type->id == ZigTypeIdUnreachable)
+ continue;
+ }
ira->instruction_index += 1;
}
@@ -23668,7 +23859,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdDeclVarSrc:
case IrInstructionIdDeclVarGen:
case IrInstructionIdStorePtr:
- case IrInstructionIdCall:
+ case IrInstructionIdCallSrc:
+ case IrInstructionIdCallGen:
case IrInstructionIdReturn:
case IrInstructionIdUnreachable:
case IrInstructionIdSetCold:
@@ -23731,6 +23923,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFieldPtr:
case IrInstructionIdElemPtr:
case IrInstructionIdVarPtr:
+ case IrInstructionIdReturnPtr:
case IrInstructionIdTypeOf:
case IrInstructionIdToPtrType:
case IrInstructionIdPtrTypeChild:
@@ -23818,6 +24011,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdVectorToArray:
case IrInstructionIdArrayToVector:
case IrInstructionIdHasDecl:
+ case IrInstructionIdAllocaSrc:
+ case IrInstructionIdAllocaGen:
return false;
case IrInstructionIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index bf9ced89c5..20581a65cf 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -188,7 +188,7 @@ static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_va
fprintf(irp->f, " ");
}
fprintf(irp->f, "= ");
- ir_print_other_instruction(irp, decl_var_instruction->init_value);
+ ir_print_other_instruction(irp, decl_var_instruction->ptr);
if (decl_var_instruction->var->is_comptime != nullptr) {
fprintf(irp->f, " // comptime = ");
ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
@@ -201,7 +201,29 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name));
}
-static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
+static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var) {
+ fprintf(irp->f, "var(");
+ ir_print_other_instruction(irp, result_loc_var->base.source_instruction);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ zig_unreachable();
+ case ResultLocIdNone:
+ fprintf(irp->f, "none");
+ return;
+ case ResultLocIdReturn:
+ fprintf(irp->f, "return");
+ return;
+ case ResultLocIdVar:
+ return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
+ }
+ zig_unreachable();
+}
+
+static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
if (call_instruction->is_async) {
fprintf(irp->f, "async");
if (call_instruction->async_allocator != nullptr) {
@@ -224,7 +246,35 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, arg);
}
- fprintf(irp->f, ")");
+ fprintf(irp->f, ")result=");
+ ir_print_result_loc(irp, call_instruction->result_loc);
+}
+
+static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) {
+ if (call_instruction->is_async) {
+ fprintf(irp->f, "async");
+ if (call_instruction->async_allocator != nullptr) {
+ fprintf(irp->f, "<");
+ ir_print_other_instruction(irp, call_instruction->async_allocator);
+ fprintf(irp->f, ">");
+ }
+ fprintf(irp->f, " ");
+ }
+ if (call_instruction->fn_entry) {
+ fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
+ } else {
+ assert(call_instruction->fn_ref);
+ ir_print_other_instruction(irp, call_instruction->fn_ref);
+ }
+ fprintf(irp->f, "(");
+ for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
+ IrInstruction *arg = call_instruction->args[i];
+ if (i != 0)
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, arg);
+ }
+ fprintf(irp->f, ")result=");
+ ir_print_other_instruction(irp, call_instruction->result_loc);
}
static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
@@ -331,6 +381,10 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));
}
+static void ir_print_return_ptr(IrPrint *irp, IrInstructionReturnPtr *instruction) {
+ fprintf(irp->f, "@ReturnPtr");
+}
+
static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, ".*");
@@ -1064,6 +1118,16 @@ static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instru
fprintf(irp->f, ")");
}
+static void ir_print_alloca_src(IrPrint *irp, IrInstructionAllocaSrc *instruction) {
+ fprintf(irp->f, "Alloca(align=");
+ ir_print_other_instruction(irp, instruction->align);
+ fprintf(irp->f, ",name=%s)", instruction->name_hint);
+}
+
+static void ir_print_alloca_gen(IrPrint *irp, IrInstructionAllocaGen *instruction) {
+ fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint);
+}
+
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
fprintf(irp->f, "inttoerr ");
ir_print_other_instruction(irp, instruction->target);
@@ -1446,7 +1510,7 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va
fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
var->align_bytes);
- ir_print_other_instruction(irp, decl_var_instruction->init_value);
+ ir_print_other_instruction(irp, decl_var_instruction->var_ptr);
if (decl_var_instruction->var->is_comptime != nullptr) {
fprintf(irp->f, " // comptime = ");
ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
@@ -1485,8 +1549,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdCast:
ir_print_cast(irp, (IrInstructionCast *)instruction);
break;
- case IrInstructionIdCall:
- ir_print_call(irp, (IrInstructionCall *)instruction);
+ case IrInstructionIdCallSrc:
+ ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);
+ break;
+ case IrInstructionIdCallGen:
+ ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);
break;
case IrInstructionIdUnOp:
ir_print_un_op(irp, (IrInstructionUnOp *)instruction);
@@ -1521,6 +1588,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdVarPtr:
ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);
break;
+ case IrInstructionIdReturnPtr:
+ ir_print_return_ptr(irp, (IrInstructionReturnPtr *)instruction);
+ break;
case IrInstructionIdLoadPtr:
ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
break;
@@ -1938,6 +2008,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdUndeclaredIdent:
ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction);
break;
+ case IrInstructionIdAllocaSrc:
+ ir_print_alloca_src(irp, (IrInstructionAllocaSrc *)instruction);
+ break;
+ case IrInstructionIdAllocaGen:
+ ir_print_alloca_gen(irp, (IrInstructionAllocaGen *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
--
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/ir_print.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 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/ir_print.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 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/ir_print.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/ir_print.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 76a3938d69e23a22ee2d5db971737c532ee8a6b0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 7 Jun 2019 11:34:47 -0400
Subject: no-copy semantics for peer result function calls
```zig
export fn entry() void {
var c = true;
var x = if (c) foo() else bar();
}
```
```llvm
define void @entry() #2 !dbg !35 {
Entry:
%c = alloca i1, align 1
%x = alloca %Foo, align 4
store i1 true, i1* %c, align 1, !dbg !47
call void @llvm.dbg.declare(metadata i1* %c, metadata !39, metadata !DIExpression()), !dbg !48
%0 = load i1, i1* %c, align 1, !dbg !49
br i1 %0, label %Then, label %Else, !dbg !49
Then: ; preds = %Entry
call fastcc void @foo(%Foo* sret %x), !dbg !50
br label %EndIf, !dbg !51
Else: ; preds = %Entry
call fastcc void @bar(%Foo* sret %x), !dbg !52
br label %EndIf, !dbg !51
EndIf: ; preds = %Else, %Then
call void @llvm.dbg.declare(metadata %Foo* %x, metadata !42, metadata !DIExpression()), !dbg !53
ret void, !dbg !54
}
```
---
BRANCH_TODO | 8 +++
src/all_types.hpp | 4 +-
src/ir.cpp | 190 ++++++++++++++++++++++++++++++++++--------------------
src/ir_print.cpp | 9 ++-
4 files changed, 137 insertions(+), 74 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index b1d21ca1a4..76ee7c24d9 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -31,3 +31,11 @@ inferred comptime
handle if with no else
+
+
+static IrInstruction *ir_const_unreachable(IrAnalyze *ira, IrInstruction *source_instruction) {
+ IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_unreachable);
+ result->value.special = ConstValSpecialStatic;
+ return result;
+}
+
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 6f504efd9c..c5e9eb06d8 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3590,8 +3590,10 @@ enum ResultLocId {
struct ResultLoc {
ResultLocId id;
+ bool written;
+ IrInstruction *resolved_loc; // result ptr
IrInstruction *source_instruction;
- IrInstruction *gen_instruction;
+ IrInstruction *gen_instruction; // value to store to the result loc
ZigType *implicit_elem_type;
};
diff --git a/src/ir.cpp b/src/ir.cpp
index 393d2a8589..8614593390 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -185,7 +185,8 @@ 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(IrAnalyze *ira, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value);
+static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -1376,11 +1377,8 @@ 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,
- ResultLoc *result_loc, ZigType *return_type)
+ IrInstruction *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;
@@ -1392,14 +1390,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 = resolved_result_loc;
+ call_instruction->result_loc = 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)
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 (call_instruction->result_loc != nullptr) ir_ref_instruction(call_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 &call_instruction->base;
}
@@ -5366,7 +5364,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
incoming_blocks[1] = after_else_block;
IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
- return ir_lval_wrap(irb, scope, phi, lval, result_loc);
+ return ir_expr_wrap(irb, scope, phi, result_loc);
}
static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
@@ -6558,10 +6556,11 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
return true;
}
-static void next_peer_block(ZigList *list, IrBasicBlock *next_bb) {
- if (list->length >= 2) {
- list->at(list->length - 2).next_bb = next_bb;
+static void next_peer_block(ResultLocPeerParent *peer_parent, IrBasicBlock *next_bb) {
+ if (peer_parent->peer_count > 0) {
+ peer_parent->peers[peer_parent->peer_count - 1].next_bb = next_bb;
}
+ peer_parent->peer_count += 1;
}
static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
@@ -6600,8 +6599,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
ResultLocPeerParent *peer_parent = allocate(1);
peer_parent->base.id = ResultLocIdPeerParent;
peer_parent->parent = result_loc;
-
- ZigList peer_result_locs = {};
+ peer_parent->peers = allocate(prong_count);
+ peer_parent->peer_count = 0;
// First do the else and the ranges
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
@@ -6611,7 +6610,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
size_t prong_item_count = prong_node->data.switch_prong.items.length;
if (prong_item_count == 0) {
- ResultLocPeer *this_peer_result_loc = peer_result_locs.add_one();
+ ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];
this_peer_result_loc->base.id = ResultLocIdPeer;
this_peer_result_loc->parent = peer_parent;
if (else_prong) {
@@ -6624,7 +6623,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
else_prong = prong_node;
IrBasicBlock *prev_block = irb->current_basic_block;
- next_peer_block(&peer_result_locs, else_block);
+ next_peer_block(peer_parent, else_block);
ir_set_cursor_at_end_and_append_block(irb, else_block);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
@@ -6634,7 +6633,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
ir_set_cursor_at_end(irb, prev_block);
} else if (prong_node->data.switch_prong.any_items_are_range) {
- ResultLocPeer *this_peer_result_loc = peer_result_locs.add_one();
+ ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];
this_peer_result_loc->base.id = ResultLocIdPeer;
this_peer_result_loc->parent = peer_parent;
@@ -6697,7 +6696,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,
range_block_no, is_comptime));
- next_peer_block(&peer_result_locs, range_block_yes);
+ next_peer_block(peer_parent, range_block_yes);
ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,
@@ -6719,7 +6718,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
if (prong_node->data.switch_prong.any_items_are_range)
continue;
- ResultLocPeer *this_peer_result_loc = peer_result_locs.add_one();
+ ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];
this_peer_result_loc->base.id = ResultLocIdPeer;
this_peer_result_loc->parent = peer_parent;
@@ -6746,7 +6745,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
IrBasicBlock *prev_block = irb->current_basic_block;
- next_peer_block(&peer_result_locs, prong_block);
+ next_peer_block(peer_parent, prong_block);
ir_set_cursor_at_end_and_append_block(irb, prong_block);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,
@@ -6773,22 +6772,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
br_instruction = &switch_br->base;
}
- for (size_t i = 0; i < peer_result_locs.length; i += 1) {
- peer_result_locs.at(i).base.source_instruction = br_instruction;
+ for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
+ peer_parent->peers[i].base.source_instruction = br_instruction;
}
peer_parent->base.source_instruction = br_instruction;
- peer_parent->peer_count = peer_result_locs.length;
- peer_parent->peers = peer_result_locs.items;
if (!else_prong) {
- if (peer_result_locs.length != 0) {
- peer_result_locs.last().next_bb = else_block;
+ if (peer_parent->peer_count != 0) {
+ peer_parent->peers[peer_parent->peer_count - 1].next_bb = else_block;
}
ir_set_cursor_at_end_and_append_block(irb, else_block);
ir_build_unreachable(irb, scope, node);
} else {
- if (peer_result_locs.length != 0) {
- peer_result_locs.last().next_bb = end_block;
+ if (peer_parent->peer_count != 0) {
+ peer_parent->peers[peer_parent->peer_count - 1].next_bb = end_block;
}
}
@@ -14400,12 +14397,12 @@ 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
-static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, ZigType *value_type,
- IrInstruction *value)
+// when calling this function, at the callsite must check for result type noreturn and propagate it up
+static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
+ ResultLoc *result_loc, ZigType *value_type, IrInstruction *value)
{
- if (result_loc->implicit_elem_type != nullptr) {
- // already resolved
- return nullptr;
+ if (result_loc->resolved_loc != nullptr) {
+ return result_loc->resolved_loc;
}
result_loc->gen_instruction = value;
result_loc->implicit_elem_type = value_type;
@@ -14420,12 +14417,12 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, Z
assert(result_loc->source_instruction->id == IrInstructionIdAllocaSrc);
IrInstructionAllocaSrc *alloca_src =
reinterpret_cast(result_loc->source_instruction);
+ 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);
if (alloca_src->base.child == nullptr) {
- 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;
@@ -14441,18 +14438,67 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, ResultLoc *result_loc, Z
alloca_src->name_hint, force_comptime);
}
alloca_src->base.child = alloca_gen;
- return is_comptime ? nullptr : alloca_src->base.child;
}
- return nullptr;
+ result_loc->written = true;
+ result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child;
+ return result_loc->resolved_loc;
}
case ResultLocIdReturn: {
bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
if (is_comptime) return nullptr;
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);
+ result_loc->written = true;
+ result_loc->resolved_loc = ir_build_return_ptr(ira, result_loc->source_instruction, ptr_return_type);
+ return result_loc->resolved_loc;
+ }
+ case ResultLocIdPeer: {
+ ResultLocPeer *result_peer = reinterpret_cast(result_loc);
+ ResultLocPeerParent *peer_parent = result_peer->parent;
+
+ if (ira->const_predecessor_bb)
+ return nullptr;
+
+ if (peer_parent->resolved_type == nullptr) {
+ IrInstruction *suspended_inst = ira_suspend(ira, suspend_source_instr,
+ 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) {
+ ResultLocPeer *this_peer = &peer_parent->peers[i];
+ ResultLocPeer *opposite_peer = &peer_parent->peers[peer_parent->peer_count - i - 1];
+
+ IrInstruction *gen_instruction = this_peer->base.gen_instruction;
+ if (gen_instruction == nullptr) {
+ instructions[i] = ir_const(ira, this_peer->base.source_instruction,
+ this_peer->base.implicit_elem_type);
+ instructions[i]->value.special = ConstValSpecialRuntime;
+ } else {
+ instructions[i] = gen_instruction;
+ }
+ if (opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable) {
+ ira->resume_stack.append(opposite_peer->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 *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
+ peer_parent->resolved_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->resolved_loc = parent_result_loc;
+ return result_loc->resolved_loc;
}
- case ResultLocIdPeer:
- return nullptr;
}
zig_unreachable();
}
@@ -14504,7 +14550,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
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,
+ casted_args, FnInlineAuto, true, async_allocator_inst, nullptr, nullptr,
async_return_type);
}
@@ -15246,6 +15292,14 @@ 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;
+ }
+
if (fn_type_can_fail(impl_fn_type_id)) {
parent_fn_entry->calls_or_awaits_errorable_fn = true;
}
@@ -15257,10 +15311,11 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
return ir_finish_anal(ira, result);
}
+ call_instruction->result_loc->written = true;
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,
- call_instruction->is_async, nullptr, casted_new_stack, call_instruction->result_loc,
+ call_instruction->is_async, nullptr, casted_new_stack, result_loc,
impl_fn_type_id->return_type);
return ir_finish_anal(ira, new_call_instruction);
@@ -15355,9 +15410,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;
+ }
+
+ call_instruction->result_loc->written = true;
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,
- call_instruction->result_loc, return_type);
+ result_loc, return_type);
return ir_finish_anal(ira, new_call_instruction);
}
@@ -23619,35 +23683,19 @@ 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->id == ResultLocIdPeer) {
- ResultLocPeer *result_peer = reinterpret_cast(instruction->result_loc);
- ResultLocPeerParent *peer_parent = result_peer->parent;
+ if (!instruction->result_loc->written) {
+ IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+ value->value.type, value);
+ if (result_loc != nullptr) {
+ if (type_is_invalid(result_loc->value.type))
+ return ira->codegen->invalid_instruction;
+ if (result_loc->value.type->id == ZigTypeIdUnreachable)
+ return result_loc;
- 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);
+ instruction->result_loc->written = true;
+ ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
}
}
- IrInstruction *result_loc = ir_resolve_result(ira, instruction->result_loc, value->value.type, value);
- if (result_loc != nullptr && !type_is_invalid(result_loc->value.type)) {
- ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
- }
return ir_const_void(ira, &instruction->base);
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index dbc5ea364c..7d56b157d5 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -207,6 +207,12 @@ static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var)
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);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
switch (result_loc->id) {
case ResultLocIdInvalid:
@@ -220,8 +226,7 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
case ResultLocIdVar:
return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
case ResultLocIdPeer:
- fprintf(irp->f, "peer");
- return;
+ return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
case ResultLocIdPeerParent:
fprintf(irp->f, "peer_parent");
return;
--
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/ir_print.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 3ec766abe38a892346e56a47ec0fa4c27eda2995 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 9 Jun 2019 10:46:13 -0400
Subject: remove ResultLocField dead code
---
src/all_types.hpp | 9 ---------
src/ir.cpp | 42 ------------------------------------------
src/ir_print.cpp | 8 --------
3 files changed, 59 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index fbd788c9d9..810c6b2be7 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3588,7 +3588,6 @@ enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
ResultLocIdVar,
- ResultLocIdField,
ResultLocIdReturn,
ResultLocIdPeer,
ResultLocIdPeerParent,
@@ -3615,14 +3614,6 @@ struct ResultLocVar {
ZigVar *var;
};
-struct ResultLocField {
- ResultLoc base;
-
- ResultLoc *parent;
- Buf *name;
- IrInstruction *container_type;
-};
-
struct ResultLocReturn {
ResultLoc base;
};
diff --git a/src/ir.cpp b/src/ir.cpp
index d34630554c..bea6d2702d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -14504,28 +14504,6 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspe
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:
@@ -14606,26 +14584,6 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
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;
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 0f80a9b9e3..9181f66be5 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -213,12 +213,6 @@ static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *
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);
@@ -239,8 +233,6 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
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:
--
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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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/ir_print.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 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/ir_print.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 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/ir_print.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 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/ir_print.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/ir_print.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 74250e434eb4ba0d752808e6a7b8d647e545c420 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 17 Jun 2019 16:27:45 -0400
Subject: inferred comptime union inits
---
src/all_types.hpp | 1 -
src/ir.cpp | 156 +++++++++++++++++++++++++++++-------------------------
src/ir_print.cpp | 2 +-
3 files changed, 85 insertions(+), 74 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index f63d6a902b..164c62f37d 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2646,7 +2646,6 @@ struct IrInstructionContainerInitList {
struct IrInstructionContainerInitFieldsField {
Buf *name;
- IrInstruction *value;
AstNode *source_node;
TypeStructField *type_struct_field;
IrInstruction *result_loc;
diff --git a/src/ir.cpp b/src/ir.cpp
index 32f6b4c22a..95b181918e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1555,7 +1555,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
ir_ref_instruction(container_type, irb->current_basic_block);
for (size_t i = 0; i < field_count; i += 1) {
- ir_ref_instruction(fields[i].value, irb->current_basic_block);
+ ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
}
if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
@@ -5783,7 +5783,6 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
return expr_value;
fields[i].name = name;
- fields[i].value = expr_value;
fields[i].source_node = entry_node;
fields[i].result_loc = field_ptr;
}
@@ -17182,69 +17181,89 @@ 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 == ZigTypeIdEnum) {
+ }
+
+ if (bare_type->id == ZigTypeIdEnum) {
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
source_instr, container_ptr, container_type);
- } else if (bare_type->id == ZigTypeIdUnion) {
+ }
+
+ 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)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
- if (!ptr_val)
+ if (field == nullptr) {
+ return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
+ source_instr, container_ptr, container_type);
+ }
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
+ is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
+ 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 *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
+ if (union_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (type_is_invalid(union_val->type))
return ira->codegen->invalid_instruction;
- if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
- if (union_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (type_is_invalid(union_val->type))
- return ira->codegen->invalid_instruction;
+ if (initializing) {
+ 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;
+ }
- 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();
+ union_val->special = ConstValSpecialStatic;
+ bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
+ union_val->data.x_union.payload = payload_val;
+ } 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;
+ ConstExprValue *payload_val = union_val->data.x_union.payload;
- ZigType *field_type = field->type_entry;
- ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
- is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
- IrInstruction *result = ir_const(ira, source_instr, ptr_type);
- ConstExprValue *const_val = &result->value;
- const_val->data.x_ptr.special = ConstPtrSpecialRef;
- const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
- const_val->data.x_ptr.data.ref.pointee = payload_val;
- return result;
+ 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);
+ 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 = ConstPtrSpecialRef;
+ const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
+ const_val->data.x_ptr.data.ref.pointee = payload_val;
+ return result;
}
-
- 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;
- } else {
- return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
- source_instr, container_ptr, container_type);
}
- } else {
- zig_unreachable();
+
+ IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, container_ptr, field, initializing);
+ result->value.type = ptr_type;
+ return result;
}
+
+ zig_unreachable();
}
static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
@@ -18891,12 +18910,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
}
IrInstructionContainerInitFieldsField *field = &fields[0];
- 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;
TypeUnionField *type_field = find_union_type_field(container_type, field->name);
- if (!type_field) {
+ if (type_field == nullptr) {
ir_add_error_node(ira, field->source_node,
buf_sprintf("no member named '%s' in union '%s'",
buf_ptr(field->name), buf_ptr(&container_type->name)));
@@ -18906,33 +18925,26 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
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;
-
- if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->invalid_instruction;
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (instr_is_comptime(field_result_loc) &&
+ field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
+ {
+ result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ } else {
+ result_loc->value.special = ConstValSpecialRuntime;
+ }
+ }
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
|| type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
- if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
- !type_has_bits(casted_field_value->value.type))
- {
- ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
- if (!field_val)
- return ira->codegen->invalid_instruction;
-
- IrInstruction *result = ir_const(ira, instruction, container_type);
- ConstExprValue *out_val = &result->value;
- out_val->data.x_union.payload = field_val;
- out_val->data.x_union.tag = type_field->enum_field->value;
- out_val->parent.id = ConstParentIdUnion;
- out_val->parent.data.p_union.union_val = out_val;
- return result;
+ IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
+ if (is_comptime && !instr_is_comptime(result)) {
+ ir_add_error(ira, field->result_loc,
+ buf_sprintf("unable to evaluate constant expression"));
+ return ira->codegen->invalid_instruction;
}
-
- return ir_get_deref(ira, instruction, result_loc, nullptr);
+ return result;
}
static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index b66827fb92..6934ebda5a 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -364,7 +364,7 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
const char *comma = (i == 0) ? "" : ", ";
fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
- ir_print_other_instruction(irp, field->value);
+ ir_print_other_instruction(irp, field->result_loc);
}
fprintf(irp->f, "} // container init");
}
--
cgit v1.2.3
From 4e182c7e9e44a97fe925344057b7b30c3ff2cae4 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 17 Jun 2019 17:46:03 -0400
Subject: inferred comptime array inits
---
src/all_types.hpp | 2 +-
src/ir.cpp | 232 ++++++++++++++++++++++++++++++------------------------
src/ir_print.cpp | 4 +-
3 files changed, 130 insertions(+), 108 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 164c62f37d..711e8f2a10 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2640,7 +2640,7 @@ struct IrInstructionContainerInitList {
IrInstruction *container_type;
IrInstruction *elem_type;
size_t item_count;
- IrInstruction **items;
+ IrInstruction **elem_result_loc_list;
IrInstruction *result_loc;
};
diff --git a/src/ir.cpp b/src/ir.cpp
index 22fbc688c1..585f17bcbb 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1524,18 +1524,19 @@ 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, size_t item_count, IrInstruction **items, IrInstruction *result_loc)
+ IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list,
+ IrInstruction *result_loc)
{
IrInstructionContainerInitList *container_init_list_instruction =
ir_build_instruction(irb, scope, source_node);
container_init_list_instruction->container_type = container_type;
container_init_list_instruction->item_count = item_count;
- container_init_list_instruction->items = items;
+ container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
container_init_list_instruction->result_loc = result_loc;
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);
+ ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
}
if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
@@ -5802,7 +5803,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
container_type);
- IrInstruction **values = allocate(item_count);
+ IrInstruction **result_locs = allocate(item_count);
for (size_t i = 0; i < item_count; i += 1) {
AstNode *expr_node = container_init_expr->entries.at(i);
@@ -5813,16 +5814,17 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
result_loc_inst->base.id = ResultLocIdInstruction;
result_loc_inst->base.source_instruction = elem_ptr;
ir_ref_instruction(elem_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, scope, LValNone,
&result_loc_inst->base);
if (expr_value == irb->codegen->invalid_instruction)
return expr_value;
- values[i] = expr_value;
+ result_locs[i] = elem_ptr;
}
IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
- item_count, values, container_ptr);
+ item_count, result_locs, container_ptr);
return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
}
}
@@ -16891,6 +16893,22 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
if (array_ptr_val == nullptr)
return ira->codegen->invalid_instruction;
+ if (array_ptr_val->special == ConstValSpecialUndef && array_type->id == ZigTypeIdArray &&
+ elem_ptr_instruction->initializing)
+ {
+ array_ptr_val->data.x_array.special = ConstArraySpecialNone;
+ array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
+ array_ptr_val->special = ConstValSpecialStatic;
+ for (size_t i = 0; i < array_type->data.array.len; i += 1) {
+ ConstExprValue *elem_val = &array_ptr_val->data.x_array.data.s_none.elements[i];
+ elem_val->special = ConstValSpecialUndef;
+ elem_val->type = array_type->data.array.child_type;
+ elem_val->parent.id = ConstParentIdArray;
+ elem_val->parent.data.p_array.array_val = array_ptr_val;
+ elem_val->parent.data.p_array.elem_index = i;
+ }
+ }
+
if (array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != ZigTypeIdPointer ||
array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
@@ -17011,7 +17029,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
return result;
} else if (array_type->id == ZigTypeIdArray) {
- IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
+ IrInstruction *result;
+ if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+ result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
+ elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
+ false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->initializing);
+ result->value.type = return_type;
+ result->value.special = ConstValSpecialStatic;
+ } else {
+ result = ir_const(ira, &elem_ptr_instruction->base, return_type);
+ }
ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
@@ -19099,8 +19126,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstructionContainerInitList *instruction)
{
- Error err;
-
ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
@@ -19111,125 +19136,122 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
ir_add_error(ira, &instruction->base,
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) {
+ }
+
+ if (container_type->id == ZigTypeIdVoid) {
+ if (elem_count != 0) {
+ ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("void expression expects no arguments"));
+ return ira->codegen->invalid_instruction;
+ }
+ return ir_const_void(ira, &instruction->base);
+ }
+
+ if (container_type->id == ZigTypeIdStruct && elem_count == 0) {
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;
- if (container_type->id == ZigTypeIdArray) {
- child_type = container_type->data.array.child_type;
- if (container_type->data.array.len != elem_count) {
- ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
-
- ir_add_error(ira, &instruction->base,
- buf_sprintf("expected %s literal, found %s literal",
- buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
- return ira->codegen->invalid_instruction;
- }
- } else {
- ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
- assert(pointer_type->id == ZigTypeIdPointer);
- child_type = pointer_type->data.pointer.child_type;
- }
-
- if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) {
- return ira->codegen->invalid_instruction;
- }
+ }
- ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
+ if (container_type->id != ZigTypeIdArray) {
+ ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("type '%s' does not support array initialization",
+ buf_ptr(&container_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
- ConstExprValue const_val = {};
- const_val.special = ConstValSpecialStatic;
- const_val.type = fixed_size_array_type;
- // const_val.global_refs = allocate(1);
- const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
+ 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;
+ ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
+ ZigType *child_type = container_type->data.array.child_type;
+ if (container_type->data.array.len != elem_count) {
+ ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
- IrInstruction **new_items = allocate(elem_count);
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("expected %s literal, found %s literal",
+ buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
- IrInstruction *first_non_const_instruction = nullptr;
+ bool is_comptime;
+ switch (type_requires_comptime(ira->codegen, container_type)) {
+ case ReqCompTimeInvalid:
+ return ira->codegen->invalid_instruction;
+ case ReqCompTimeNo:
+ is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
+ break;
+ case ReqCompTimeYes:
+ is_comptime = true;
+ break;
+ }
- for (size_t i = 0; i < elem_count; i += 1) {
- IrInstruction *arg_value = instruction->items[i]->child;
- if (type_is_invalid(arg_value->value.type))
- return ira->codegen->invalid_instruction;
+ IrInstruction *first_non_const_instruction = nullptr;
- IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
- if (casted_arg == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
+ // The Result Location Mechanism has already emitted runtime instructions to
+ // initialize runtime elements and has omitted instructions for the comptime
+ // elements. However it is only now that we find out whether the array initialization
+ // can be a comptime value. So we must clean up the situation. If it turns out
+ // array initialization can be a comptime value, overwrite ConstPtrMutInfer with
+ // ConstPtrMutComptimeConst. Otherwise, emit instructions to runtime-initialize the
+ // elements that have comptime-known values.
+ ZigList const_ptrs = {};
- new_items[i] = casted_arg;
+ for (size_t i = 0; i < elem_count; i += 1) {
+ IrInstruction *elem_result_loc = instruction->elem_result_loc_list[i]->child;
+ if (type_is_invalid(elem_result_loc->value.type))
+ return ira->codegen->invalid_instruction;
- if (const_val.special == ConstValSpecialStatic) {
- if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
- ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
- if (!elem_val)
- return ira->codegen->invalid_instruction;
+ assert(elem_result_loc->value.type->id == ZigTypeIdPointer);
- copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
- } else {
- first_non_const_instruction = casted_arg;
- const_val.special = ConstValSpecialRuntime;
- }
- }
+ if (instr_is_comptime(elem_result_loc) &&
+ elem_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
+ {
+ const_ptrs.append(elem_result_loc);
+ } else {
+ first_non_const_instruction = elem_result_loc;
}
+ }
- if (const_val.special == ConstValSpecialStatic) {
- IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
- ConstExprValue *out_val = &result->value;
- copy_const_val(out_val, &const_val, false);
- result->value.type = fixed_size_array_type;
- for (size_t i = 0; i < elem_count; i += 1) {
- ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
- ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdArray;
- parent->data.p_array.array_val = out_val;
- parent->data.p_array.elem_index = i;
- }
+ if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+ if (const_ptrs.length == elem_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 *elem_result_loc = const_ptrs.at(i);
+ assert(elem_result_loc->value.special == ConstValSpecialStatic);
+ IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
+ elem_result_loc->value.special = ConstValSpecialRuntime;
+ ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref);
}
- return result;
}
+ }
- if (is_comptime) {
- ir_add_error_node(ira, first_non_const_instruction->source_node,
- buf_sprintf("unable to evaluate constant expression"));
- return ira->codegen->invalid_instruction;
- }
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, result_loc, nullptr);
+ if (instr_is_comptime(result))
+ return result;
- 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;
- ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
- ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
- if (is_slice(result_elem_type)) {
- ErrorMsg *msg = ir_add_error(ira, &instruction->base,
- buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
- buf_ptr(&result_elem_type->name)));
- add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
- buf_sprintf("this value is not comptime-known"));
- return ira->codegen->invalid_instruction;
- }
- return ir_get_deref(ira, &instruction->base, result_loc, nullptr);
- } else if (container_type->id == ZigTypeIdVoid) {
- if (elem_count != 0) {
- ir_add_error_node(ira, instruction->base.source_node,
- buf_sprintf("void expression expects no arguments"));
- return ira->codegen->invalid_instruction;
- }
- return ir_const_void(ira, &instruction->base);
- } else {
- ir_add_error_node(ira, instruction->base.source_node,
- buf_sprintf("type '%s' does not support array initialization",
- buf_ptr(&container_type->name)));
+ if (is_comptime) {
+ ir_add_error_node(ira, first_non_const_instruction->source_node,
+ buf_sprintf("unable to evaluate constant expression"));
+ return ira->codegen->invalid_instruction;
+ }
+
+ ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
+ if (is_slice(result_elem_type)) {
+ ErrorMsg *msg = ir_add_error(ira, &instruction->base,
+ buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
+ buf_ptr(&result_elem_type->name)));
+ add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
+ buf_sprintf("this value is not comptime-known"));
return ira->codegen->invalid_instruction;
}
+ return result;
}
static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 6934ebda5a..c512185e00 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -348,10 +348,10 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
} else {
for (size_t i = 0; i < instruction->item_count; i += 1) {
- IrInstruction *item = instruction->items[i];
+ IrInstruction *result_loc = instruction->elem_result_loc_list[i];
if (i != 0)
fprintf(irp->f, ", ");
- ir_print_other_instruction(irp, item);
+ ir_print_other_instruction(irp, result_loc);
}
}
fprintf(irp->f, "}");
--
cgit v1.2.3
From 0498bd40d9bb941454c9008c566a3599ea8f6f6b Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 20 Jun 2019 22:38:40 -0400
Subject: fix loops with multiple break statements
---
BRANCH_TODO | 7 +-
src/all_types.hpp | 5 +-
src/ir.cpp | 257 +++++++++++++++++++++++++----------------
src/ir_print.cpp | 6 +-
test/stage1/behavior/for.zig | 16 +++
test/stage1/behavior/while.zig | 45 ++++++++
6 files changed, 224 insertions(+), 112 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 011630f315..066531ac3a 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -1,12 +1,7 @@
Scratch pad for stuff to do before merging master
=================================================
-uncomment all the behavior tests
-diff master branch to make sure
-
-restore bootstrap.zig to master
-
-get an empty file compiling successfully (with no panic fn override)
+labeled break from a block
better behavior for implicit casts. for example these introduce an extra allocation/memcpy:
var x: [1]i32 = [_]i32{1};
diff --git a/src/all_types.hpp b/src/all_types.hpp
index a421722ac5..70b14785c7 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -2065,7 +2065,7 @@ struct ScopeLoop {
IrInstruction *is_comptime;
ZigList *incoming_values;
ZigList *incoming_blocks;
- ResultLoc *result_loc;
+ ResultLocPeerParent *peer_parent;
};
// This scope blocks certain things from working such as comptime continue
@@ -3682,8 +3682,7 @@ struct ResultLocPeerParent {
bool done_resuming;
IrBasicBlock *end_bb;
ResultLoc *parent;
- ResultLocPeer *peers;
- size_t peer_count;
+ ZigList peers;
ZigType *resolved_type;
IrInstruction *is_comptime;
};
diff --git a/src/ir.cpp b/src/ir.cpp
index c3ed14770f..0645193454 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -3964,25 +3964,23 @@ 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 *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
- IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent, IrInstruction *is_comptime)
+static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
+ ResultLocPeer *result = allocate(1);
+ result->base.id = ResultLocIdPeer;
+ result->base.source_instruction = peer_parent->base.source_instruction;
+ result->parent = peer_parent;
+ return result;
+}
+
+static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
+ IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
{
ResultLocPeerParent *peer_parent = allocate(1);
peer_parent->base.id = ResultLocIdPeerParent;
peer_parent->base.source_instruction = cond_br_inst;
- peer_parent->end_bb = endif_block;
+ peer_parent->end_bb = end_block;
peer_parent->is_comptime = is_comptime;
peer_parent->parent = parent;
- 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;
IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();
ir_assert(popped_inst == cond_br_inst, cond_br_inst);
@@ -3993,6 +3991,20 @@ static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstr
return peer_parent;
}
+static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
+ IrBasicBlock *else_block, IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
+{
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime);
+
+ peer_parent->peers.append(create_peer_result(peer_parent));
+ peer_parent->peers.last()->next_bb = else_block;
+
+ peer_parent->peers.append(create_peer_result(peer_parent));
+ peer_parent->peers.last()->next_bb = end_block;
+
+ return peer_parent;
+}
+
static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
ResultLoc *result_loc)
{
@@ -4024,7 +4036,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
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);
+ IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, lval,
+ &peer_parent->peers.at(0)->base);
if (null_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_null_block = irb->current_basic_block;
@@ -4034,7 +4047,7 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
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, 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);
+ ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
IrBasicBlock *after_ok_block = irb->current_basic_block;
ir_build_br(irb, parent_scope, node, end_block, is_comptime);
@@ -5545,7 +5558,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval,
- &peer_parent->peers[0].base);
+ &peer_parent->peers.at(0)->base);
if (then_expr_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -5555,12 +5568,12 @@ 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_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);
+ else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
if (else_expr_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
- ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers[1].base);
+ ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
@@ -6004,12 +6017,12 @@ 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 {
- // for the purposes of the source instruction to ir_build_binary_result_peers
+ // for the purposes of the source instruction to ir_build_result_peers
cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
- result_loc, is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
+ is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
if (var_symbol) {
@@ -6030,7 +6043,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
loop_scope->lval = lval;
- loop_scope->result_loc = &peer_parent->peers[0].base;
+ loop_scope->peer_parent = peer_parent;
// Note the body block of the loop is not the place that lval and result_loc are used -
// it's actually in break statements, handled similarly to return statements.
@@ -6066,7 +6079,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
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_extra(irb, else_node, err_scope, lval, &peer_parent->peers[1].base);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+ IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -6080,6 +6098,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_result);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
incoming_blocks.items, incoming_values.items, peer_parent);
@@ -6107,12 +6128,12 @@ 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 {
- // for the purposes of the source instruction to ir_build_binary_result_peers
+ // for the purposes of the source instruction to ir_build_result_peers
cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
- result_loc, is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
+ is_comptime);
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, false);
@@ -6130,7 +6151,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
loop_scope->lval = lval;
- loop_scope->result_loc = &peer_parent->peers[0].base;
+ loop_scope->peer_parent = peer_parent;
// Note the body block of the loop is not the place that lval and result_loc are used -
// it's actually in break statements, handled similarly to return statements.
@@ -6159,7 +6180,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
if (else_node) {
ir_set_cursor_at_end_and_append_block(irb, else_block);
- else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_parent->peers[1].base);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+ else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -6174,6 +6200,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_result);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
incoming_blocks.items, incoming_values.items, peer_parent);
@@ -6191,12 +6220,12 @@ 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 {
- // for the purposes of the source instruction to ir_build_binary_result_peers
+ // for the purposes of the source instruction to ir_build_result_peers
cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
- result_loc, is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
+ is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
ZigList incoming_values = {0};
@@ -6211,7 +6240,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
loop_scope->lval = lval;
- loop_scope->result_loc = &peer_parent->peers[0].base;
+ loop_scope->peer_parent = peer_parent;
// Note the body block of the loop is not the place that lval and result_loc are used -
// it's actually in break statements, handled similarly to return statements.
@@ -6240,7 +6269,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
if (else_node) {
ir_set_cursor_at_end_and_append_block(irb, else_block);
- else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+
+ else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -6255,6 +6290,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_result);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
incoming_blocks.items, incoming_values.items, peer_parent);
@@ -6327,8 +6365,7 @@ 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 = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
- result_loc, is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, 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,
@@ -6351,7 +6388,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
loop_scope->incoming_blocks = &incoming_blocks;
loop_scope->incoming_values = &incoming_values;
loop_scope->lval = lval;
- loop_scope->result_loc = &peer_parent->peers[0].base;
+ loop_scope->peer_parent = peer_parent;
// Note the body block of the loop is not the place that lval and result_loc are used -
// it's actually in break statements, handled similarly to return statements.
@@ -6372,7 +6409,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
if (else_node) {
ir_set_cursor_at_end_and_append_block(irb, else_block);
- else_result = ir_gen_node_extra(irb, else_node, parent_scope, lval, &peer_parent->peers[1].base);
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ ResultLocPeer *peer_result = create_peer_result(peer_parent);
+ peer_parent->peers.append(peer_result);
+ else_result = ir_gen_node_extra(irb, else_node, parent_scope, lval, &peer_result->base);
if (else_result == irb->codegen->invalid_instruction)
return else_result;
if (!instr_is_unreachable(else_result))
@@ -6388,6 +6430,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
incoming_blocks.append(after_cond_block);
incoming_values.append(void_else_value);
}
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
+ }
IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length,
incoming_blocks.items, incoming_values.items, peer_parent);
@@ -6728,7 +6773,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
var_scope = subexpr_scope;
}
IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
- &peer_parent->peers[0].base);
+ &peer_parent->peers.at(0)->base);
if (then_expr_result == irb->codegen->invalid_instruction)
return then_expr_result;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -6738,12 +6783,12 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
ir_set_cursor_at_end_and_append_block(irb, else_block);
IrInstruction *else_expr_result;
if (else_node) {
- else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);
+ else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
if (else_expr_result == irb->codegen->invalid_instruction)
return else_expr_result;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
- ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers[1].base);
+ ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
@@ -6811,7 +6856,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
var_scope = subexpr_scope;
}
IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
- &peer_parent->peers[0].base);
+ &peer_parent->peers.at(0)->base);
if (then_expr_result == irb->codegen->invalid_instruction)
return then_expr_result;
IrBasicBlock *after_then_block = irb->current_basic_block;
@@ -6835,12 +6880,12 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
} else {
err_var_scope = subexpr_scope;
}
- else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers[1].base);
+ else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base);
if (else_expr_result == irb->codegen->invalid_instruction)
return else_expr_result;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
- ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers[1].base);
+ ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
@@ -6910,13 +6955,6 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
return true;
}
-static void next_peer_block(ResultLocPeerParent *peer_parent, IrBasicBlock *next_bb) {
- if (peer_parent->peer_count > 0) {
- peer_parent->peers[peer_parent->peer_count - 1].next_bb = next_bb;
- }
- peer_parent->peer_count += 1;
-}
-
static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
ResultLoc *result_loc)
{
@@ -6955,8 +6993,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
peer_parent->end_bb = end_block;
peer_parent->is_comptime = is_comptime;
peer_parent->parent = result_loc;
- peer_parent->peers = allocate(prong_count);
- peer_parent->peer_count = 0;
ir_build_reset_result(irb, scope, node, &peer_parent->base);
@@ -6968,9 +7004,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
size_t prong_item_count = prong_node->data.switch_prong.items.length;
if (prong_item_count == 0) {
- ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];
- this_peer_result_loc->base.id = ResultLocIdPeer;
- this_peer_result_loc->parent = peer_parent;
+ ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
if (else_prong) {
ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
buf_sprintf("multiple else prongs in switch expression"));
@@ -6981,7 +7015,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
else_prong = prong_node;
IrBasicBlock *prev_block = irb->current_basic_block;
- next_peer_block(peer_parent, else_block);
+ if (peer_parent->peers.length > 0) {
+ peer_parent->peers.last()->next_bb = else_block;
+ }
+ peer_parent->peers.append(this_peer_result_loc);
ir_set_cursor_at_end_and_append_block(irb, else_block);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
@@ -6991,9 +7028,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
ir_set_cursor_at_end(irb, prev_block);
} else if (prong_node->data.switch_prong.any_items_are_range) {
- ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];
- this_peer_result_loc->base.id = ResultLocIdPeer;
- this_peer_result_loc->parent = peer_parent;
+ ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
IrInstruction *ok_bit = nullptr;
AstNode *last_item_node = nullptr;
@@ -7054,7 +7089,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,
range_block_no, is_comptime));
- next_peer_block(peer_parent, range_block_yes);
+ if (peer_parent->peers.length > 0) {
+ peer_parent->peers.last()->next_bb = range_block_yes;
+ }
+ peer_parent->peers.append(this_peer_result_loc);
ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,
@@ -7076,9 +7114,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
if (prong_node->data.switch_prong.any_items_are_range)
continue;
- ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];
- this_peer_result_loc->base.id = ResultLocIdPeer;
- this_peer_result_loc->parent = peer_parent;
+ ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");
IrInstruction **items = allocate(prong_item_count);
@@ -7103,7 +7139,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
IrBasicBlock *prev_block = irb->current_basic_block;
- next_peer_block(peer_parent, prong_block);
+ if (peer_parent->peers.length > 0) {
+ peer_parent->peers.last()->next_bb = prong_block;
+ }
+ peer_parent->peers.append(this_peer_result_loc);
ir_set_cursor_at_end_and_append_block(irb, prong_block);
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,
@@ -7130,20 +7169,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
}
br_instruction = &switch_br->base;
}
- for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
- peer_parent->peers[i].base.source_instruction = br_instruction;
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ peer_parent->peers.at(i)->base.source_instruction = br_instruction;
}
peer_parent->base.source_instruction = br_instruction;
if (!else_prong) {
- if (peer_parent->peer_count != 0) {
- peer_parent->peers[peer_parent->peer_count - 1].next_bb = else_block;
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = else_block;
}
ir_set_cursor_at_end_and_append_block(irb, else_block);
ir_build_unreachable(irb, scope, node);
} else {
- if (peer_parent->peer_count != 0) {
- peer_parent->peers[peer_parent->peer_count - 1].next_bb = end_block;
+ if (peer_parent->peers.length != 0) {
+ peer_parent->peers.last()->next_bb = end_block;
}
}
@@ -7247,8 +7286,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
IrInstruction *result_value;
if (node->data.break_expr.expr) {
+ ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent);
+ loop_scope->peer_parent->peers.append(peer_result);
+
result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope,
- loop_scope->lval, loop_scope->result_loc);
+ loop_scope->lval, &peer_result->base);
if (result_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
@@ -7421,7 +7463,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
} else {
err_scope = parent_scope;
}
- IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, lval, &peer_parent->peers[0].base);
+ IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, lval, &peer_parent->peers.at(0)->base);
if (err_result == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
IrBasicBlock *after_err_block = irb->current_basic_block;
@@ -7431,7 +7473,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
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, 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);
+ ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
IrBasicBlock *after_ok_block = irb->current_basic_block;
ir_build_br(irb, parent_scope, node, end_block, is_comptime);
@@ -10939,25 +10981,7 @@ static IrInstruction *ira_resume(IrAnalyze *ira) {
return ira->codegen->unreach_instruction;
}
-static void ir_finish_bb(IrAnalyze *ira) {
- if (!ira->new_irb.current_basic_block->already_appended) {
- ira->new_irb.current_basic_block->already_appended = true;
- if (ira->codegen->verbose_ir) {
- fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint,
- ira->new_irb.current_basic_block->debug_id);
- }
- ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
- }
- ira->instruction_index += 1;
- while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
- IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
- if (!next_instruction->is_gen) {
- ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
- break;
- }
- ira->instruction_index += 1;
- }
-
+static void ir_start_next_bb(IrAnalyze *ira) {
ira->old_bb_index += 1;
bool need_repeat = true;
@@ -11006,6 +11030,28 @@ static void ir_finish_bb(IrAnalyze *ira) {
}
}
+static void ir_finish_bb(IrAnalyze *ira) {
+ if (!ira->new_irb.current_basic_block->already_appended) {
+ ira->new_irb.current_basic_block->already_appended = true;
+ if (ira->codegen->verbose_ir) {
+ fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint,
+ ira->new_irb.current_basic_block->debug_id);
+ }
+ ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
+ }
+ ira->instruction_index += 1;
+ while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
+ IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
+ if (!next_instruction->is_gen) {
+ ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
+ break;
+ }
+ ira->instruction_index += 1;
+ }
+
+ ir_start_next_bb(ira);
+}
+
static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
ira->old_bb_index = SIZE_MAX;
ira->new_irb.exec->invalid = true;
@@ -15036,7 +15082,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
if (peer_parent->end_bb->suspend_instruction_ref == nullptr) {
peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr;
}
- return ira_suspend(ira, suspend_source_instr, result_peer->next_bb, &result_peer->suspend_pos);
+ IrInstruction *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb,
+ &result_peer->suspend_pos);
+ if (result_peer->next_bb == nullptr) {
+ ir_start_next_bb(ira);
+ }
+ return unreach_inst;
}
IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
@@ -15194,8 +15245,8 @@ static void ir_reset_result(ResultLoc *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);
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ ir_reset_result(&peer_parent->peers.at(i)->base);
}
break;
}
@@ -16615,11 +16666,13 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
}
ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
- if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming) {
+ if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
+ peer_parent->peers.length != 0)
+ {
if (peer_parent->resolved_type == nullptr) {
- IrInstruction **instructions = allocate(peer_parent->peer_count);
- for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
- ResultLocPeer *this_peer = &peer_parent->peers[i];
+ IrInstruction **instructions = allocate(peer_parent->peers.length);
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ ResultLocPeer *this_peer = peer_parent->peers.at(i);
IrInstruction *gen_instruction = this_peer->base.gen_instruction;
if (gen_instruction == nullptr) {
@@ -16639,7 +16692,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, 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);
+ peer_parent->peers.length);
// 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);
@@ -16673,8 +16726,8 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
ir_push_resume(ira, suspend_pos);
- for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
- ResultLocPeer *opposite_peer = &peer_parent->peers[peer_parent->peer_count - i - 1];
+ for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
+ ResultLocPeer *opposite_peer = peer_parent->peers.at(peer_parent->peers.length - i - 1);
if (opposite_peer->base.implicit_elem_type != nullptr &&
opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
{
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index c512185e00..9ba7527417 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -57,7 +57,11 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)
}
static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
- fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);
+ if (bb == nullptr) {
+ fprintf(irp->f, "(null block)");
+ } else {
+ fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);
+ }
}
static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
diff --git a/test/stage1/behavior/for.zig b/test/stage1/behavior/for.zig
index f670b04c00..63205b9e7d 100644
--- a/test/stage1/behavior/for.zig
+++ b/test/stage1/behavior/for.zig
@@ -110,3 +110,19 @@ fn testContinueOuter() void {
}
expect(counter == array.len);
}
+
+test "2 break statements and an else" {
+ const S = struct {
+ fn entry(t: bool, f: bool) void {
+ var buf: [10]u8 = undefined;
+ var ok = false;
+ ok = for (buf) |item| {
+ if (f) break false;
+ if (t) break true;
+ } else false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
diff --git a/test/stage1/behavior/while.zig b/test/stage1/behavior/while.zig
index 29ad90ed17..58ff713c23 100644
--- a/test/stage1/behavior/while.zig
+++ b/test/stage1/behavior/while.zig
@@ -226,3 +226,48 @@ fn returnFalse() bool {
fn returnTrue() bool {
return true;
}
+
+test "while bool 2 break statements and an else" {
+ const S = struct {
+ fn entry(t: bool, f: bool) void {
+ var ok = false;
+ ok = while (t) {
+ if (f) break false;
+ if (t) break true;
+ } else false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
+
+test "while optional 2 break statements and an else" {
+ const S = struct {
+ fn entry(opt_t: ?bool, f: bool) void {
+ var ok = false;
+ ok = while (opt_t) |t| {
+ if (f) break false;
+ if (t) break true;
+ } else false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
+
+test "while error 2 break statements and an else" {
+ const S = struct {
+ fn entry(opt_t: anyerror!bool, f: bool) void {
+ var ok = false;
+ ok = while (opt_t) |t| {
+ if (f) break false;
+ if (t) break true;
+ } else |_| false;
+ expect(ok);
+ }
+ };
+ S.entry(true, false);
+ comptime S.entry(true, false);
+}
--
cgit v1.2.3
From df11512f85e5228ee2393e9dc5fc42294ecba1c9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 2 Jul 2019 16:52:55 -0400
Subject: fixups
---
doc/langref.html.in | 23 +++++++++++---------
src/all_types.hpp | 3 +--
src/ir.cpp | 45 +++++++++++++++++----------------------
src/ir_print.cpp | 2 +-
test/compile_errors.zig | 9 ++++++++
test/stage1/behavior/hasfield.zig | 11 ++++++++--
6 files changed, 52 insertions(+), 41 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 78c2723148..fda741930b 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -6801,6 +6801,19 @@ test "@hasDecl" {
assert(!@hasDecl(Foo, "nope1234"));
}
{#code_end#}
+ {#see_also|@hasField#}
+ {#header_close#}
+
+ {#header_open|@hasField#}
+ {#syntax#}@hasField(comptime T: type, comptime name: []const u8) bool{#endsyntax#}
+ Returns whether the field name of a struct, union, or enum exists.
+
+ The result is a compile time constant.
+
+
+ It does not include functions, variables, or constants.
+
+ {#see_also|@hasDecl#}
{#header_close#}
{#header_open|@import#}
@@ -6940,16 +6953,6 @@ fn add(a: i32, b: i32) i32 { return a + b; }
It does not include functions, variables, or constants.
{#header_close#}
- {#header_open|@hasField#}
- {#syntax#}@hasField(comptime T: type, comptime name: []const u8) bool{#endsyntax#}
- Returns if the field name of a struct, union, or enum exists.
-
- The result is a compile time constant.
-
-
- It does not include functions, variables, constants.
-
- {#header_close#}
{#header_open|@memberType#}
{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}
Returns the field type of a struct or union.
diff --git a/src/all_types.hpp b/src/all_types.hpp
index ada08983a6..a9304fdd0f 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3339,8 +3339,7 @@ struct IrInstructionHasField {
IrInstruction base;
IrInstruction *container_type;
- Buf *field_name_buffer;
- IrInstruction *field_name_expr;
+ IrInstruction *field_name;
};
struct IrInstructionTypeId {
diff --git a/src/ir.cpp b/src/ir.cpp
index 6f3ea2220b..e6cc5f2342 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1380,15 +1380,14 @@ static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *
}
static IrInstruction *ir_build_has_field(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_type, IrInstruction *field_name_expr)
+ IrInstruction *container_type, IrInstruction *field_name)
{
IrInstructionHasField *instruction = ir_build_instruction(irb, scope, source_node);
instruction->container_type = container_type;
- instruction->field_name_buffer = nullptr;
- instruction->field_name_expr = field_name_expr;
+ instruction->field_name = field_name;
ir_ref_instruction(container_type, irb->current_basic_block);
- ir_ref_instruction(field_name_expr, irb->current_basic_block);
+ ir_ref_instruction(field_name, irb->current_basic_block);
return &instruction->base;
}
@@ -5132,7 +5131,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return arg1_value;
IrInstruction *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, type_info, lval);
+ return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
}
case BuiltinFnIdTypeInfo:
{
@@ -22655,36 +22654,30 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr
static IrInstruction *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstructionHasField *instruction) {
Error err;
- IrInstruction *container_type_value = instruction->container_type->child;
- ZigType *container_type = ir_resolve_type(ira, container_type_value);
+ ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
- if ((err = ensure_complete_type(ira->codegen, container_type)))
+ if ((err = type_resolve(ira->codegen, container_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
- Buf *field_name = instruction->field_name_buffer;
- if (!field_name) {
- IrInstruction *field_name_expr = instruction->field_name_expr->child;
- field_name = ir_resolve_str(ira, field_name_expr);
- if (!field_name)
- return ira->codegen->invalid_instruction;
- }
+ Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
+ if (field_name == nullptr)
+ return ira->codegen->invalid_instruction;
bool result;
- if (container_type->id == ZigTypeIdStruct)
- result = (bool)find_struct_type_field(container_type, field_name);
- else if (container_type->id == ZigTypeIdEnum)
- result = (bool)find_enum_type_field(container_type, field_name);
- else if (container_type->id == ZigTypeIdUnion)
- result = (bool)find_union_type_field(container_type, field_name);
- else {
- ir_add_error(ira, container_type_value,
- buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name)));
+ if (container_type->id == ZigTypeIdStruct) {
+ result = find_struct_type_field(container_type, field_name) != nullptr;
+ } else if (container_type->id == ZigTypeIdEnum) {
+ result = find_enum_type_field(container_type, field_name) != nullptr;
+ } else if (container_type->id == ZigTypeIdUnion) {
+ result = find_union_type_field(container_type, field_name) != nullptr;
+ } else {
+ ir_add_error(ira, instruction->container_type,
+ buf_sprintf("type '%s' does not support @hasField", buf_ptr(&container_type->name)));
return ira->codegen->invalid_instruction;
}
- return ir_build_const_bool(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, result);
+ return ir_const_bool(ira, &instruction->base, result);
}
static IrInstruction *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) {
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 3b6ee3273e..31b7e608b7 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1274,7 +1274,7 @@ static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction)
fprintf(irp->f, "@hasField(");
ir_print_other_instruction(irp, instruction->container_type);
fprintf(irp->f, ",");
- ir_print_other_instruction(irp, instruction->field_name_expr);
+ ir_print_other_instruction(irp, instruction->field_name);
fprintf(irp->f, ")");
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 94cd152eb7..e0ac76bbf0 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "wrong type to @hasField",
+ \\export fn entry() bool {
+ \\ return @hasField(i32, "hi");
+ \\}
+ ,
+ "tmp.zig:2:22: error: type 'i32' does not support @hasField",
+ );
+
cases.add(
"slice passed as array init type with elems",
\\export fn entry() void {
diff --git a/test/stage1/behavior/hasfield.zig b/test/stage1/behavior/hasfield.zig
index 0e18cb19b5..c179fedd56 100644
--- a/test/stage1/behavior/hasfield.zig
+++ b/test/stage1/behavior/hasfield.zig
@@ -5,26 +5,33 @@ test "@hasField" {
const struc = struct {
a: i32,
b: []u8,
+
+ pub const nope = 1;
};
expect(@hasField(struc, "a") == true);
expect(@hasField(struc, "b") == true);
expect(@hasField(struc, "non-existant") == false);
+ expect(@hasField(struc, "nope") == false);
const unin = union {
a: u64,
b: []u16,
+
+ pub const nope = 1;
};
expect(@hasField(unin, "a") == true);
expect(@hasField(unin, "b") == true);
expect(@hasField(unin, "non-existant") == false);
+ expect(@hasField(unin, "nope") == false);
const enm = enum {
a,
b,
+
+ pub const nope = 1;
};
expect(@hasField(enm, "a") == true);
expect(@hasField(enm, "b") == true);
expect(@hasField(enm, "non-existant") == false);
-
- expect(@hasField(builtin, "os") == true);
+ expect(@hasField(enm, "nope") == false);
}
--
cgit v1.2.3
From 4bae87764fc455f4df8b9d96be856921b0dd97db Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 3 Jul 2019 13:40:40 -0400
Subject: update `@unionInit` to integrate with result location semantics
---
doc/langref.html.in | 17 ++++++
src/all_types.hpp | 3 +-
src/ir.cpp | 167 ++++++++++++++++++++++++++++++----------------------
src/ir_print.cpp | 4 +-
4 files changed, 118 insertions(+), 73 deletions(-)
(limited to 'src/ir_print.cpp')
diff --git a/doc/langref.html.in b/doc/langref.html.in
index fda741930b..ef914375f4 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -5065,6 +5065,12 @@ test "@intToPtr for pointer to zero bit type" {
{#header_close#}
{#header_close#}
+ {#header_open|Result Location Semantics#}
+
+ TODO add documentation for this
+
+ {#header_close#}
+
{#header_open|comptime#}
Zig places importance on the concept of whether an expression is known at compile-time.
@@ -7809,6 +7815,17 @@ pub const TypeInfo = union(TypeId) {
{#header_close#}
+ {#header_open|@unionInit#}
+
{#syntax#}@unionInit(comptime Union: type, comptime active_field_name: []const u8, init_expr) Union{#endsyntax#}
+
+ This is the same thing as {#link|union#} initialization syntax, except that the field name is a
+ {#link|comptime#}-known value rather than an identifier token.
+
+
+ {#syntax#}@unionInit{#endsyntax#} forwards its {#link|result location|Result Location Semantics#} to {#syntax#}init_expr{#endsyntax#}.
+
+ {#header_close#}
+
{#header_open|@Vector#}
{#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 0d187a1c4e..c1e54baf8d 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -3610,7 +3610,8 @@ struct IrInstructionUnionInitNamedField {
IrInstruction *union_type;
IrInstruction *field_name;
- IrInstruction *value;
+ IrInstruction *field_result_loc;
+ IrInstruction *result_loc;
};
struct IrInstructionHasDecl {
diff --git a/src/ir.cpp b/src/ir.cpp
index 594f61982a..6b19ce2909 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -198,6 +198,9 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *
IrInstruction *base_ptr, bool initializing);
static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *ptr, IrInstruction *uncasted_value);
+static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
+ LVal lval, ResultLoc *parent_result_loc);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -1069,7 +1072,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *)
return IrInstructionIdAssertNonNull;
}
-<<<<<<< HEAD
static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) {
return IrInstructionIdHasDecl;
}
@@ -1357,12 +1359,13 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s
}
static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_ptr, IrInstruction *field_name_expr)
+ IrInstruction *container_ptr, IrInstruction *field_name_expr, bool initializing)
{
IrInstructionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node);
instruction->container_ptr = container_ptr;
instruction->field_name_buffer = nullptr;
instruction->field_name_expr = field_name_expr;
+ instruction->initializing = initializing;
ir_ref_instruction(container_ptr, irb->current_basic_block);
ir_ref_instruction(field_name_expr, irb->current_basic_block);
@@ -3329,16 +3332,19 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
-static IrInstruction *ir_build_union_init_2(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *union_type_value, IrInstruction *field_name_expr, IrInstruction *value) {
- IrInstructionUnionInit2 *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->union_type_value = union_type_value;
- instruction->field_name_expr = field_name_expr;
- instruction->value = value;
+static IrInstruction *ir_build_union_init_named_field(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type, IrInstruction *field_name, IrInstruction *field_result_loc, IrInstruction *result_loc)
+{
+ IrInstructionUnionInitNamedField *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->union_type = union_type;
+ instruction->field_name = field_name;
+ instruction->field_result_loc = field_result_loc;
+ instruction->result_loc = result_loc;
- ir_ref_instruction(union_type_value, irb->current_basic_block);
- ir_ref_instruction(field_name_expr, irb->current_basic_block);
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(union_type, irb->current_basic_block);
+ ir_ref_instruction(field_name, irb->current_basic_block);
+ ir_ref_instruction(field_result_loc, irb->current_basic_block);
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
return &instruction->base;
}
@@ -5130,7 +5136,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, arg0_value, arg1_value);
+ IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node,
+ arg0_value, arg1_value, false);
if (lval == LValPtr)
return ptr_instruction;
@@ -5673,26 +5680,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
case BuiltinFnIdUnionInit:
{
+ AstNode *union_type_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *union_type_inst = ir_gen_node(irb, union_type_node, scope);
+ if (union_type_inst == irb->codegen->invalid_instruction)
+ return union_type_inst;
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_instruction)
- return arg0_value;
-
- AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
- if (arg1_value == irb->codegen->invalid_instruction)
- return arg1_value;
-
- AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
- IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
- if (arg2_value == irb->codegen->invalid_instruction)
- return arg2_value;
+ AstNode *name_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *name_inst = ir_gen_node(irb, name_node, scope);
+ if (name_inst == irb->codegen->invalid_instruction)
+ return name_inst;
- IrInstruction *result = ir_build_union_init_2(irb, scope, node, arg0_value, arg1_value, arg2_value);
+ AstNode *init_node = node->data.fn_call_expr.params.at(2);
- // TODO: Not sure if we need ir_lval_wrap or not.
- return result;
+ return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
+ lval, result_loc);
}
}
zig_unreachable();
@@ -5972,6 +5973,31 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
zig_unreachable();
}
+static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
+ LVal lval, ResultLoc *parent_result_loc)
+{
+ IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type);
+ IrInstruction *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr,
+ field_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, scope, LValNone,
+ &result_loc_inst->base);
+ if (expr_value == irb->codegen->invalid_instruction)
+ return expr_value;
+
+ IrInstruction *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type,
+ field_name, field_ptr, container_ptr);
+
+ return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc);
+}
+
static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
ResultLoc *parent_result_loc)
{
@@ -19451,32 +19477,21 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile);
}
-static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
- ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
- IrInstruction *result_loc)
+static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *source_instruction,
+ AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstruction *field_result_loc,
+ IrInstruction *result_loc)
{
Error err;
- assert(container_type->id == ZigTypeIdUnion);
-
- if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_instruction;
-
- if (instr_field_count != 1) {
- ir_add_error(ira, instruction,
- buf_sprintf("union initialization expects exactly one field"));
- return ira->codegen->invalid_instruction;
- }
+ assert(union_type->id == ZigTypeIdUnion);
- IrInstructionContainerInitFieldsField *field = &fields[0];
- IrInstruction *field_result_loc = field->result_loc->child;
- if (type_is_invalid(field_result_loc->value.type))
+ if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
- TypeUnionField *type_field = find_union_type_field(container_type, field->name);
+ TypeUnionField *type_field = find_union_type_field(union_type, field_name);
if (type_field == nullptr) {
- ir_add_error_node(ira, field->source_node,
+ ir_add_error_node(ira, field_source_node,
buf_sprintf("no member named '%s' in union '%s'",
- buf_ptr(field->name), buf_ptr(&container_type->name)));
+ buf_ptr(field_name), buf_ptr(&union_type->name)));
return ira->codegen->invalid_instruction;
}
@@ -19493,12 +19508,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
}
}
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
- || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
+ bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instruction->scope)
+ || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes;
- IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
+ IrInstruction *result = ir_get_deref(ira, source_instruction, result_loc, nullptr);
if (is_comptime && !instr_is_comptime(result)) {
- ir_add_error(ira, field->result_loc,
+ ir_add_error(ira, field_result_loc,
buf_sprintf("unable to evaluate constant expression"));
return ira->codegen->invalid_instruction;
}
@@ -19511,8 +19526,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
{
Error err;
if (container_type->id == ZigTypeIdUnion) {
- return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
- fields, result_loc);
+ if (instr_field_count != 1) {
+ ir_add_error(ira, instruction,
+ buf_sprintf("union initialization expects exactly one field"));
+ return ira->codegen->invalid_instruction;
+ }
+ IrInstructionContainerInitFieldsField *field = &fields[0];
+ IrInstruction *field_result_loc = field->result_loc->child;
+ if (type_is_invalid(field_result_loc->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_analyze_union_init(ira, instruction, field->source_node, container_type, field->name,
+ field_result_loc, result_loc);
}
if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
ir_add_error(ira, instruction,
@@ -25369,33 +25394,33 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst
return instruction->result_loc_bit_cast->parent->gen_instruction;
}
-static IrInstruction *ir_analyze_instruction_union_init_2(IrAnalyze *ira, IrInstructionUnionInit2 *union_init_instruction)
+static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira,
+ IrInstructionUnionInitNamedField *instruction)
{
- Error err;
- IrInstruction *union_type_value = union_init_instruction->union_type_value->child;
- ZigType *union_type = ir_resolve_type(ira, union_type_value);
- if (type_is_invalid(union_type)) {
+ ZigType *union_type = ir_resolve_type(ira, instruction->union_type->child);
+ if (type_is_invalid(union_type))
return ira->codegen->invalid_instruction;
- }
- if (union_type->id != ZigTypeIdUnion)
+ if (union_type->id != ZigTypeIdUnion) {
+ ir_add_error(ira, instruction->union_type,
+ buf_sprintf("non-union type '%s' passed to @unionInit", buf_ptr(&union_type->name)));
return ira->codegen->invalid_instruction;
+ }
- if ((err = ensure_complete_type(ira->codegen, union_type)))
+ Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
+ if (field_name == nullptr)
return ira->codegen->invalid_instruction;
- IrInstruction *field_name_expr = union_init_instruction->field_name_expr->child;
- Buf *field_name = ir_resolve_str(ira, field_name_expr);
- if (!field_name)
+ IrInstruction *field_result_loc = instruction->field_result_loc->child;
+ if (type_is_invalid(field_result_loc->value.type))
return ira->codegen->invalid_instruction;
- IrInstructionContainerInitFieldsField *fields = allocate(1);
-
- fields[0].name = field_name;
- fields[0].value = union_init_instruction->value;
- fields[0].source_node = union_init_instruction->base.source_node;
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return ira->codegen->invalid_instruction;
- return ir_analyze_container_init_fields_union(ira, &union_init_instruction->base, union_type, 1, fields);
+ return ir_analyze_union_init(ira, &instruction->base, instruction->base.source_node,
+ union_type, field_name, field_result_loc, result_loc);
}
static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 3ecb7fb683..588a9b2882 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1632,7 +1632,9 @@ static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInit
fprintf(irp->f, ", ");
ir_print_other_instruction(irp, instruction->field_name);
fprintf(irp->f, ", ");
- ir_print_other_instruction(irp, instruction->value);
+ ir_print_other_instruction(irp, instruction->field_result_loc);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->result_loc);
fprintf(irp->f, ")");
}
--
cgit v1.2.3