Date: Fri, 21 Sep 2018 14:15:58 -0400
Subject: [PATCH 017/127] fixups
---
doc/langref.html.in | 40 ++++++++++++++-------
src/ir.cpp | 32 ++++++++++-------
std/c/darwin.zig | 26 +++++++-------
test/cases/sizeof_and_typeof.zig | 61 +++++++++++++++++++++-----------
test/compile_errors.zig | 8 ++---
5 files changed, 104 insertions(+), 63 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index ef37d657dc..f28c8d6cfa 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1947,6 +1947,15 @@ test "linked list" {
assert(list2.first.?.data == 1234);
}
{#code_end#}
+ {#header_open|packed struct#}
+ {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout.
+ TODO bit fields
+ TODO alignment
+ TODO endianness
+ TODO @bitOffsetOf and @byteOffsetOf
+ TODO mention how volatile loads and stores of bit packed fields could be more efficient when
+ done by hand instead of with packed struct
+ {#header_close#}
{#header_open|struct Naming#}
Since all structs are anonymous, Zig infers the type name based on a few rules.
@@ -5135,6 +5144,18 @@ fn seq(c: u8) void {
Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.
{#header_close#}
+ {#header_open|@bitOffsetOf#}
+
{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
+
+ Returns the bit offset of a field relative to its containing struct.
+
+
+ For non {#link|packed structs|packed struct#}, this will always be divisible by {#syntax#}8{#endsyntax#}.
+ For packed structs, non-byte-aligned fields will share a byte offset, but they will have different
+ bit offsets.
+
+ {#see_also|@byteOffsetOf#}
+ {#header_close#}
{#header_open|@breakpoint#}
{#syntax#}@breakpoint(){#endsyntax#}
@@ -5145,6 +5166,13 @@ fn seq(c: u8) void {
This function is only valid within function scope.
+ {#header_close#}
+ {#header_open|@byteOffsetOf#}
+ {#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
+
+ Returns the byte offset of a field relative to its containing struct.
+
+ {#see_also|@bitOffsetOf#}
{#header_close#}
{#header_open|@alignCast#}
{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}
@@ -5868,18 +5896,6 @@ fn add(a: i32, b: i32) i32 {
{#see_also|@inlineCall#}
{#header_close#}
- {#header_open|@offsetOf#}
- {#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
-
- This function returns the byte offset of a field relative to its containing struct.
-
- {#header_close#}
- {#header_open|@bitOffsetOf#}
- @bitOffsetOf(comptime T: type, comptime field_name: [] const u8) (number literal)
-
- This function returns the bit offset of a field relative to its containing struct.
-
- {#header_close#}
{#header_open|@OpaqueType#}
{#syntax#}@OpaqueType() type{#endsyntax#}
diff --git a/src/ir.cpp b/src/ir.cpp
index 7daff2ca0e..5e0f79ec13 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17088,30 +17088,36 @@ static ZigType *ir_analyze_instruction_byte_offset_of(IrAnalyze *ira,
IrInstructionByteOffsetOf *instruction)
{
IrInstruction *type_value = instruction->type_value->other;
+ if (type_is_invalid(type_value->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
IrInstruction *field_name_value = instruction->field_name->other;
size_t byte_offset = 0;
- if (validate_byte_offset(ira, type_value, field_name_value, &byte_offset)) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, byte_offset);
- return ira->codegen->builtin_types.entry_num_lit_int;
- }
- return ira->codegen->builtin_types.entry_invalid;
+ if (!validate_byte_offset(ira, type_value, field_name_value, &byte_offset))
+ return ira->codegen->builtin_types.entry_invalid;
+
+
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ bigint_init_unsigned(&out_val->data.x_bigint, byte_offset);
+ return ira->codegen->builtin_types.entry_num_lit_int;
}
static ZigType *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
IrInstructionBitOffsetOf *instruction)
{
IrInstruction *type_value = instruction->type_value->other;
+ if (type_is_invalid(type_value->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
IrInstruction *field_name_value = instruction->field_name->other;
size_t byte_offset = 0;
TypeStructField *field = nullptr;
- if ((field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset))) {
- size_t bit_offset = byte_offset * 8 + field->packed_bits_offset;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, bit_offset);
- return ira->codegen->builtin_types.entry_num_lit_int;
- }
- return ira->codegen->builtin_types.entry_invalid;
+ if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset)))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ size_t bit_offset = byte_offset * 8 + field->packed_bits_offset;
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ bigint_init_unsigned(&out_val->data.x_bigint, bit_offset);
+ return ira->codegen->builtin_types.entry_num_lit_int;
}
static void ensure_field_index(ZigType *type, const char *field_name, size_t index)
diff --git a/std/c/darwin.zig b/std/c/darwin.zig
index 2e238e40eb..86c5e4828e 100644
--- a/std/c/darwin.zig
+++ b/std/c/darwin.zig
@@ -158,12 +158,12 @@ const std = @import("../index.zig");
const assert = std.debug.assert;
comptime {
- assert(@offsetOf(Kevent, "ident") == 0);
- assert(@offsetOf(Kevent, "filter") == 8);
- assert(@offsetOf(Kevent, "flags") == 10);
- assert(@offsetOf(Kevent, "fflags") == 12);
- assert(@offsetOf(Kevent, "data") == 16);
- assert(@offsetOf(Kevent, "udata") == 24);
+ assert(@byteOffsetOf(Kevent, "ident") == 0);
+ assert(@byteOffsetOf(Kevent, "filter") == 8);
+ assert(@byteOffsetOf(Kevent, "flags") == 10);
+ assert(@byteOffsetOf(Kevent, "fflags") == 12);
+ assert(@byteOffsetOf(Kevent, "data") == 16);
+ assert(@byteOffsetOf(Kevent, "udata") == 24);
}
pub const kevent64_s = extern struct {
@@ -180,11 +180,11 @@ pub const kevent64_s = extern struct {
// to make sure the struct is laid out the same. These values were
// produced from C code using the offsetof macro.
comptime {
- assert(@offsetOf(kevent64_s, "ident") == 0);
- assert(@offsetOf(kevent64_s, "filter") == 8);
- assert(@offsetOf(kevent64_s, "flags") == 10);
- assert(@offsetOf(kevent64_s, "fflags") == 12);
- assert(@offsetOf(kevent64_s, "data") == 16);
- assert(@offsetOf(kevent64_s, "udata") == 24);
- assert(@offsetOf(kevent64_s, "ext") == 32);
+ assert(@byteOffsetOf(kevent64_s, "ident") == 0);
+ assert(@byteOffsetOf(kevent64_s, "filter") == 8);
+ assert(@byteOffsetOf(kevent64_s, "flags") == 10);
+ assert(@byteOffsetOf(kevent64_s, "fflags") == 12);
+ assert(@byteOffsetOf(kevent64_s, "data") == 16);
+ assert(@byteOffsetOf(kevent64_s, "udata") == 24);
+ assert(@byteOffsetOf(kevent64_s, "ext") == 32);
}
diff --git a/test/cases/sizeof_and_typeof.zig b/test/cases/sizeof_and_typeof.zig
index 2d1ffa9434..11c6b2f6ba 100644
--- a/test/cases/sizeof_and_typeof.zig
+++ b/test/cases/sizeof_and_typeof.zig
@@ -1,13 +1,14 @@
+const builtin = @import("builtin");
const assert = @import("std").debug.assert;
-test "sizeofAndTypeOf" {
+test "@sizeOf and @typeOf" {
const y: @typeOf(x) = 120;
assert(@sizeOf(@typeOf(y)) == 2);
}
const x: u16 = 13;
const z: @typeOf(x) = 19;
-const S = struct {
+const A = struct {
a: u8,
b: u32,
c: u8,
@@ -27,24 +28,42 @@ const P = packed struct {
g: u16,
};
-test "byteOffsetOf" {
- const p: P = undefined;
- std.debug.assert(@byteOffsetOf(P, "a") == 0 and @byteOffsetOf(S, "a") == 0);
- std.debug.assert(@byteOffsetOf(P, "b") == 1 and @byteOffsetOf(S, "b") == 4);
- std.debug.assert(@byteOffsetOf(P, "c") == 5 and @byteOffsetOf(S, "c") == 8);
- std.debug.assert(@byteOffsetOf(P, "d") == 6 and @byteOffsetOf(S, "d") == 9);
- std.debug.assert(@byteOffsetOf(P, "e") == 6 and @byteOffsetOf(S, "e") == 10);
- std.debug.assert(@byteOffsetOf(P, "f") == 7 and @byteOffsetOf(S, "f") == 12);
- std.debug.assert(@byteOffsetOf(P, "g") == 9 and @byteOffsetOf(S, "g") == 14);
+test "@byteOffsetOf" {
+ // Packed structs have fixed memory layout
+ assert(@byteOffsetOf(P, "a") == 0);
+ assert(@byteOffsetOf(P, "b") == 1);
+ assert(@byteOffsetOf(P, "c") == 5);
+ assert(@byteOffsetOf(P, "d") == 6);
+ assert(@byteOffsetOf(P, "e") == 6);
+ assert(@byteOffsetOf(P, "f") == 7);
+ assert(@byteOffsetOf(P, "g") == 9);
+
+ // Normal struct fields can be moved/padded
+ var a: A = undefined;
+ assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
+ assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
+ assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
+ assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
+ assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
+ assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
+ assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
}
-test "bitOffsetOf" {
- const p: P = undefined;
- std.debug.assert(@bitOffsetOf(P, "a") == 0 and @bitOffsetOf(S, "a") == 0);
- std.debug.assert(@bitOffsetOf(P, "b") == 8 and @bitOffsetOf(S, "b") == 32);
- std.debug.assert(@bitOffsetOf(P, "c") == 40 and @bitOffsetOf(S, "c") == 64);
- std.debug.assert(@bitOffsetOf(P, "d") == 48 and @bitOffsetOf(S, "d") == 72);
- std.debug.assert(@bitOffsetOf(P, "e") == 51 and @bitOffsetOf(S, "e") == 80);
- std.debug.assert(@bitOffsetOf(P, "f") == 56 and @bitOffsetOf(S, "f") == 96);
- std.debug.assert(@bitOffsetOf(P, "g") == 72 and @bitOffsetOf(S, "g") == 112);
-}
\ No newline at end of file
+test "@bitOffsetOf" {
+ // Packed structs have fixed memory layout
+ assert(@bitOffsetOf(P, "a") == 0);
+ assert(@bitOffsetOf(P, "b") == 8);
+ assert(@bitOffsetOf(P, "c") == 40);
+ assert(@bitOffsetOf(P, "d") == 48);
+ assert(@bitOffsetOf(P, "e") == 51);
+ assert(@bitOffsetOf(P, "f") == 56);
+ assert(@bitOffsetOf(P, "g") == 72);
+
+ assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
+ assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
+ assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
+ assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
+ assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
+ assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
+ assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 7b659a8dc1..fae022f3fb 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -3769,7 +3769,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return @byteOffsetOf(Foo, "a",);
\\}
,
- ".tmp_source.zig:3:22: error: expected struct type, found 'i32'",
+ ".tmp_source.zig:3:26: error: expected struct type, found 'i32'",
);
cases.add(
@@ -3781,7 +3781,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return @byteOffsetOf(Foo, "a",);
\\}
,
- ".tmp_source.zig:5:27: error: struct 'Foo' has no field 'a'",
+ ".tmp_source.zig:5:31: error: struct 'Foo' has no field 'a'",
);
cases.addExe(
@@ -5092,7 +5092,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const fieldOffset = @byteOffsetOf(Empty, "val",);
\\}
,
- ".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset",
+ ".tmp_source.zig:5:46: error: zero-bit field 'val' in struct 'Empty' has no offset",
);
cases.add(
@@ -5104,7 +5104,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const fieldOffset = @bitOffsetOf(Empty, "val",);
\\}
,
- ".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset",
+ ".tmp_source.zig:5:45: error: zero-bit field 'val' in struct 'Empty' has no offset",
);
cases.add(
From 9e5cd43e6d2caaaa2226be56c0886d73a200e78b Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 21 Sep 2018 15:40:02 -0400
Subject: [PATCH 018/127] fix comptime string concatenation ignoring slice
bounds
closes #1362
---
src/ir.cpp | 5 ++++-
test/cases/eval.zig | 14 ++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 5e0f79ec13..c9bc4a48ef 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -12399,7 +12399,8 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
- op1_array_end = op1_array_val->type->data.array.len;
+ ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];
+ op1_array_end = bigint_as_unsigned(&len_val->data.x_bigint);
} else {
ir_add_error(ira, op1,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
@@ -12446,6 +12447,8 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
op2_array_end = op2_array_val->type->data.array.len;
+ ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];
+ op2_array_end = bigint_as_unsigned(&len_val->data.x_bigint);
} else {
ir_add_error(ira, op2,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index 6e64a64aee..e0c998e961 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -723,3 +723,17 @@ test "comptime pointer cast array and then slice" {
assert(sliceA[1] == 2);
assert(sliceB[1] == 2);
}
+
+test "slice bounds in comptime concatenation" {
+ const bs = comptime blk: {
+ const b = c"11";
+ break :blk b[0..1];
+ };
+ const str = "" ++ bs;
+ assert(str.len == 1);
+ assert(std.mem.eql(u8, str, "1"));
+
+ const str2 = bs ++ "";
+ assert(str2.len == 1);
+ assert(std.mem.eql(u8, str2, "1"));
+}
From 2e2740716103784334348c491a0e4d84052c5734 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 21 Sep 2018 18:47:12 -0400
Subject: [PATCH 019/127] stage1: unify 2 implementations of pointer deref
I found out there were accidentally two code paths
in zig ir for pointer dereference. So this should
fix a few bugs.
closes #1486
---
src/ir.cpp | 111 ++++++++++++++++++---------------------
test/behavior.zig | 1 +
test/cases/bugs/1486.zig | 11 ++++
test/compile_errors.zig | 2 +-
4 files changed, 64 insertions(+), 61 deletions(-)
create mode 100644 test/cases/bugs/1486.zig
diff --git a/src/ir.cpp b/src/ir.cpp
index c9bc4a48ef..a35c6380a7 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -153,6 +153,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
+static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
+ ConstExprValue *out_val, ConstExprValue *ptr_val);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -11205,27 +11207,12 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
}
static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
+ Error err;
ZigType *type_entry = ptr->value.type;
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 (instr_is_comptime(ptr)) {
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
- ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
- {
- ConstExprValue *pointee = ir_const_ptr_pointee(ira, &ptr->value, source_instruction->source_node);
- if (pointee == nullptr)
- return ira->codegen->invalid_instruction;
- if (pointee->special != ConstValSpecialRuntime) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
- source_instruction->source_node, child_type);
- copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst);
- result->value.type = child_type;
- return result;
- }
- }
- }
// dereferencing a *u0 is comptime known to be 0
if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
@@ -11233,6 +11220,29 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
init_const_unsigned_negative(&result->value, child_type, 0, false);
return result;
}
+ 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_create_const(&ira->new_irb, source_instruction->scope,
+ source_instruction->source_node, child_type);
+
+ if ((err = ir_read_const_ptr(ira, source_instruction->source_node, &result->value,
+ &ptr->value)))
+ {
+ return ira->codegen->invalid_instruction;
+ }
+ result->value.type = child_type;
+ return result;
+ }
+ }
+ }
// TODO if the instruction is a const ref instruction we can skip it
IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
source_instruction->source_node, ptr);
@@ -13931,10 +13941,16 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c
static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val)
{
+ Error err;
assert(out_val->type != nullptr);
ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val);
+ if ((err = type_resolve(ira->codegen, pointee->type, ResolveStatusSizeKnown)))
+ return ErrorSemanticAnalyzeFail;
+ if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown)))
+ return ErrorSemanticAnalyzeFail;
+
size_t src_size = type_size(ira->codegen, pointee->type);
size_t dst_size = type_size(ira->codegen, out_val->type);
@@ -13957,48 +13973,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
return ErrorNone;
}
-static ZigType *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
- Error err;
- IrInstruction *value = un_op_instruction->value->other;
-
- ZigType *ptr_type = value->value.type;
- ZigType *child_type;
- if (type_is_invalid(ptr_type)) {
- return ira->codegen->builtin_types.entry_invalid;
- } else if (ptr_type->id == ZigTypeIdPointer) {
- if (ptr_type->data.pointer.ptr_len == PtrLenUnknown) {
- ir_add_error_node(ira, un_op_instruction->base.source_node,
- buf_sprintf("index syntax required for unknown-length pointer type '%s'",
- buf_ptr(&ptr_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
- }
- child_type = ptr_type->data.pointer.child_type;
- } else {
- ir_add_error_node(ira, un_op_instruction->base.source_node,
- buf_sprintf("attempt to dereference non-pointer type '%s'",
- buf_ptr(&ptr_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
- }
-
- // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
- // one of the ptr instructions
-
- if (instr_is_comptime(value)) {
- ConstExprValue *comptime_value = ir_resolve_const(ira, value, UndefBad);
- if (comptime_value == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
-
- ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
- out_val->type = child_type;
- if ((err = ir_read_const_ptr(ira, un_op_instruction->base.source_node, out_val, comptime_value)))
- return ira->codegen->builtin_types.entry_invalid;
- return child_type;
- }
-
- ir_build_load_ptr_from(&ira->new_irb, &un_op_instruction->base, value);
- return child_type;
-}
-
static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
Error err;
IrInstruction *value = un_op_instruction->value->other;
@@ -14131,8 +14105,25 @@ static ZigType *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *
case IrUnOpNegation:
case IrUnOpNegationWrap:
return ir_analyze_negation(ira, un_op_instruction);
- case IrUnOpDereference:
- return ir_analyze_dereference(ira, un_op_instruction);
+ case IrUnOpDereference: {
+ IrInstruction *ptr = un_op_instruction->value->other;
+ if (type_is_invalid(ptr->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+ ZigType *ptr_type = ptr->value.type;
+ if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.ptr_len == PtrLenUnknown) {
+ ir_add_error_node(ira, un_op_instruction->base.source_node,
+ buf_sprintf("index syntax required for unknown-length pointer type '%s'",
+ buf_ptr(&ptr_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
+ // one of the ptr instructions
+ IrInstruction *result = ir_get_deref(ira, &un_op_instruction->base, ptr);
+ if (result == ira->codegen->invalid_instruction)
+ return ira->codegen->builtin_types.entry_invalid;
+ ir_link_new_instruction(result, &un_op_instruction->base);
+ return result->value.type;
+ }
case IrUnOpOptional:
return ir_analyze_maybe(ira, un_op_instruction);
}
diff --git a/test/behavior.zig b/test/behavior.zig
index 68d6f513c4..1d031343d6 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -15,6 +15,7 @@ comptime {
_ = @import("cases/bugs/1381.zig");
_ = @import("cases/bugs/1421.zig");
_ = @import("cases/bugs/1442.zig");
+ _ = @import("cases/bugs/1486.zig");
_ = @import("cases/bugs/394.zig");
_ = @import("cases/bugs/655.zig");
_ = @import("cases/bugs/656.zig");
diff --git a/test/cases/bugs/1486.zig b/test/cases/bugs/1486.zig
new file mode 100644
index 0000000000..98fae36d3a
--- /dev/null
+++ b/test/cases/bugs/1486.zig
@@ -0,0 +1,11 @@
+const assert = @import("std").debug.assert;
+
+const ptr = &global;
+var global: u64 = 123;
+
+test "constant pointer to global variable causes runtime load" {
+ global = 1234;
+ assert(&global == ptr);
+ assert(ptr.* == 1234);
+}
+
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index fae022f3fb..c1e25c1df9 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2896,7 +2896,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a.*;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: attempt to dereference undefined value",
);
cases.add(
From 5c15c5fc48fa61569eca7bcd49e1c819db2a90c9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 22 Sep 2018 10:04:47 -0400
Subject: [PATCH 020/127] add compile error for slice of undefined slice
closes #1293
---
src/ir.cpp | 5 +++++
test/compile_errors.zig | 10 ++++++++++
2 files changed, 15 insertions(+)
diff --git a/src/ir.cpp b/src/ir.cpp
index a35c6380a7..7e98e99af1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -19229,6 +19229,11 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
return ira->codegen->builtin_types.entry_invalid;
parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];
+ if (parent_ptr->special == ConstValSpecialUndef) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index];
switch (parent_ptr->data.x_ptr.special) {
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index c1e25c1df9..62df9f077d 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,16 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "comptime slice of an undefined slice",
+ \\comptime {
+ \\ var a: []u8 = undefined;
+ \\ var b = a[0..10];
+ \\}
+ ,
+ ".tmp_source.zig:3:14: error: slice of undefined",
+ );
+
cases.add(
"implicit cast const array to mutable slice",
\\export fn entry() void {
From 3c1f9baff10be20910fc6e168c293759d9b8537e Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 22 Sep 2018 10:22:01 -0400
Subject: [PATCH 021/127] doc: add note about reproducible builds
---
doc/langref.html.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index f28c8d6cfa..40af140c83 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -6502,6 +6502,7 @@ pub fn build(b: *Builder) void {
Safety checks enabled
Slow runtime performance
Large binary size
+ No reproducible build requirement
{#header_close#}
{#header_open|ReleaseFast#}
@@ -6511,6 +6512,7 @@ pub fn build(b: *Builder) void {
Safety checks disabled
Slow compilation speed
Large binary size
+ Reproducible build
{#header_close#}
{#header_open|ReleaseSafe#}
@@ -6520,6 +6522,7 @@ pub fn build(b: *Builder) void {
Safety checks enabled
Slow compilation speed
Large binary size
+ Reproducible build
{#header_close#}
{#header_open|ReleaseSmall#}
@@ -6529,6 +6532,7 @@ pub fn build(b: *Builder) void {
Safety checks disabled
Slow compilation speed
Small binary size
+ Reproducible build
{#header_close#}
{#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
From c84548e71d4990352c202da92d47f1398385411f Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 22 Sep 2018 10:46:22 -0400
Subject: [PATCH 022/127] fix @compileLog having unintended side effects
closes #1459
---
src/ir.cpp | 5 ++++-
test/compile_errors.zig | 17 ++++++++++++++---
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 7e98e99af1..95172e2b59 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -9874,6 +9874,7 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
if (!const_val)
return ira->codegen->builtin_types.entry_invalid;
+ assert(const_val->data.x_type != nullptr);
return const_val->data.x_type;
}
@@ -16880,7 +16881,9 @@ static ZigType *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstruction
}
fprintf(stderr, "\n");
- ir_add_error(ira, &instruction->base, buf_sprintf("found compile log statement"));
+ // Here we bypass higher level functions such as ir_add_error because we do not want
+ // invalidate_exec to be called.
+ add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
ir_build_const_from(ira, &instruction->base);
return ira->codegen->builtin_types.entry_void;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 62df9f077d..5d9fb84c71 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,20 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "compile log statement inside function which must be comptime evaluated",
+ \\fn Foo(comptime T: type) type {
+ \\ @compileLog(@typeName(T));
+ \\ return T;
+ \\}
+ \\export fn entry() void {
+ \\ _ = Foo(i32);
+ \\ _ = @typeName(Foo(i32));
+ \\}
+ ,
+ ".tmp_source.zig:2:5: error: found compile log statement",
+ );
+
cases.add(
"comptime slice of an undefined slice",
\\comptime {
@@ -3472,11 +3486,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\}
,
".tmp_source.zig:5:5: error: found compile log statement",
- ".tmp_source.zig:2:17: note: called from here",
".tmp_source.zig:6:5: error: found compile log statement",
- ".tmp_source.zig:2:17: note: called from here",
".tmp_source.zig:7:5: error: found compile log statement",
- ".tmp_source.zig:2:17: note: called from here",
);
cases.add(
From f9558444354b5b3367536a7389790c87ea9a94f0 Mon Sep 17 00:00:00 2001
From: Jeff Fowler
Date: Sat, 22 Sep 2018 12:32:54 +0200
Subject: [PATCH 023/127] rm extraneous macro
---
src/os.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/os.cpp b/src/os.cpp
index b682429884..54df5568b7 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -1378,8 +1378,6 @@ int os_init(void) {
#if defined(ZIG_OS_WINDOWS)
_setmode(fileno(stdout), _O_BINARY);
_setmode(fileno(stderr), _O_BINARY);
-#endif
-#if defined(ZIG_OS_WINDOWS)
unsigned __int64 frequency;
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) {
win32_time_resolution = 1.0 / (double) frequency;
From af01c6e2bf6a3cbf302deb9166ea3bca50d65175 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 23 Sep 2018 12:29:38 -0400
Subject: [PATCH 024/127] include LICENSE in windows static builds
---
ci/appveyor/after_build.bat | 1 +
1 file changed, 1 insertion(+)
diff --git a/ci/appveyor/after_build.bat b/ci/appveyor/after_build.bat
index 8639a0c56a..cdad0509e6 100644
--- a/ci/appveyor/after_build.bat
+++ b/ci/appveyor/after_build.bat
@@ -9,6 +9,7 @@ mkdir "%RELEASEDIR%"
move build-msvc-release\bin\zig.exe "%RELEASEDIR%"
move build-msvc-release\lib "%RELEASEDIR%"
move zig-cache\langref.html "%RELEASEDIR%"
+move LICENSE "%RELEASEDIR%"
SET "RELEASEZIP=zig-%ZIGVERSION%.zip"
From a170a64776e703a8549e5ef16cc6009b642b617e Mon Sep 17 00:00:00 2001
From: Wink Saville
Date: Sun, 23 Sep 2018 10:08:45 -0700
Subject: [PATCH 025/127] Fix typo in argsAlloc comment
Changed freeArgs to argsFree.
---
std/os/index.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/std/os/index.zig b/std/os/index.zig
index d4110bd759..d86ab119df 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -2022,7 +2022,7 @@ pub fn args() ArgIterator {
return ArgIterator.init();
}
-/// Caller must call freeArgs on result.
+/// Caller must call argsFree on result.
pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
// TODO refactor to only make 1 allocation.
var it = args();
From a155f2973b681dd984ddaba7686dc7c07347120c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 11:12:21 -0400
Subject: [PATCH 026/127] add test to cover the CLI API that godbolt is using
closes #1399
---
test/cli.zig | 55 ++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 45 insertions(+), 10 deletions(-)
diff --git a/test/cli.zig b/test/cli.zig
index f65dabc9f5..0ca806a303 100644
--- a/test/cli.zig
+++ b/test/cli.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const builtin = @import("builtin");
const os = std.os;
const assertOrPanic = std.debug.assertOrPanic;
@@ -28,8 +29,18 @@ pub fn main() !void {
});
const zig_exe = try os.path.resolve(a, zig_exe_rel);
- try testZigInitLib(zig_exe, cache_root);
- try testZigInitExe(zig_exe, cache_root);
+ const dir_path = try os.path.join(a, cache_root, "clitest");
+ const TestFn = fn ([]const u8, []const u8) error!void;
+ const test_fns = []TestFn{
+ testZigInitLib,
+ testZigInitExe,
+ testGodboltApi,
+ };
+ for (test_fns) |testFn| {
+ try os.deleteTree(a, dir_path);
+ try os.makeDir(dir_path);
+ try testFn(zig_exe, dir_path);
+ }
}
fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 {
@@ -73,20 +84,44 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult {
return result;
}
-fn testZigInitLib(zig_exe: []const u8, cache_root: []const u8) !void {
- const dir_path = try os.path.join(a, cache_root, "clitest");
- try os.deleteTree(a, dir_path);
- try os.makeDir(dir_path);
+fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
_ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" });
const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" });
assertOrPanic(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
}
-fn testZigInitExe(zig_exe: []const u8, cache_root: []const u8) !void {
- const dir_path = try os.path.join(a, cache_root, "clitest");
- try os.deleteTree(a, dir_path);
- try os.makeDir(dir_path);
+fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
_ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" });
const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" });
assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));
}
+
+fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) !void {
+ if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return;
+
+ const example_zig_path = try os.path.join(a, dir_path, "example.zig");
+ const example_s_path = try os.path.join(a, dir_path, "example.s");
+
+ try std.io.writeFile(example_zig_path,
+ \\// Type your code here, or load an example.
+ \\export fn square(num: i32) i32 {
+ \\ return num * num;
+ \\}
+ );
+
+ const args = [][]const u8{
+ zig_exe, "build-obj",
+ "--cache-dir", dir_path,
+ "--output", example_s_path,
+ "--output-h", "/dev/null",
+ "--emit", "asm",
+ "-mllvm", "--x86-asm-syntax=intel",
+ "--strip", "--release-fast",
+ example_zig_path,
+ };
+ _ = try exec(dir_path, args);
+
+ const out_asm = try std.io.readFileAlloc(a, example_s_path);
+ assertOrPanic(std.mem.indexOf(u8, out_asm, "square:") != null);
+ assertOrPanic(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);
+}
From 6d048aa3bfabf43da40966b01d8a4717bd8fe9b7 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 11:14:39 -0400
Subject: [PATCH 027/127] add panic function to godbolt CLI API test
---
test/cli.zig | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/cli.zig b/test/cli.zig
index 0ca806a303..45e961053b 100644
--- a/test/cli.zig
+++ b/test/cli.zig
@@ -107,6 +107,10 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) !void {
\\export fn square(num: i32) i32 {
\\ return num * num;
\\}
+ \\extern fn zig_panic() noreturn;
+ \\pub inline fn panic(msg: []const u8, error_return_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ zig_panic();
+ \\}
);
const args = [][]const u8{
From 8a7737eef4f9f5fd3e6d318b6985e1bf6a364438 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 12:01:51 -0400
Subject: [PATCH 028/127] fix godbolt cli test on non-linux-x86_64 hosts
---
test/cli.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/cli.zig b/test/cli.zig
index 45e961053b..5a2a51bbfd 100644
--- a/test/cli.zig
+++ b/test/cli.zig
@@ -96,7 +96,7 @@ fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));
}
-fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) !void {
+fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) error!void {
if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return;
const example_zig_path = try os.path.join(a, dir_path, "example.zig");
From 004c383292412faef7987b5fb5da73a2971176ee Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 12:19:16 -0400
Subject: [PATCH 029/127] fix translate-c incorrectly translating negative enum
init values
closes #1360
---
src/translate_c.cpp | 8 ++++++-
test/translate_c.zig | 54 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index df48c9e4a2..fd13adb8f6 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -458,7 +458,13 @@ static const char *decl_name(const Decl *decl) {
static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
node->data.int_literal.bigint = allocate(1);
- bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative());
+ bool is_negative = aps_int.isNegative();
+ if (!is_negative) {
+ bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
+ return node;
+ }
+ llvm::APSInt negated = -aps_int;
+ bigint_init_data(node->data.int_literal.bigint, negated.getRawData(), negated.getNumWords(), true);
return node;
}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index b31e515aa2..f6ce742fcd 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1,6 +1,60 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("negative enum init values",
+ \\enum EnumWithInits {
+ \\ VAL01 = 0,
+ \\ VAL02 = 1,
+ \\ VAL03 = 2,
+ \\ VAL04 = 3,
+ \\ VAL05 = -1,
+ \\ VAL06 = -2,
+ \\ VAL07 = -3,
+ \\ VAL08 = -4,
+ \\ VAL09 = VAL02 + VAL08,
+ \\ VAL10 = -1000012000,
+ \\ VAL11 = -1000161000,
+ \\ VAL12 = -1000174001,
+ \\ VAL13 = VAL09,
+ \\ VAL14 = VAL10,
+ \\ VAL15 = VAL11,
+ \\ VAL16 = VAL13,
+ \\ VAL17 = (VAL16 - VAL10 + 1),
+ \\ VAL18 = 0x1000000000000000L,
+ \\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
+ \\ VAL20 = VAL19 + VAL19,
+ \\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
+ \\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
+ \\ VAL23 = 0xFFFFFFFFFFFFFFFF,
+ \\};
+ ,
+ \\pub const enum_EnumWithInits = extern enum(c_longlong) {
+ \\ VAL01 = 0,
+ \\ VAL02 = 1,
+ \\ VAL03 = 2,
+ \\ VAL04 = 3,
+ \\ VAL05 = -1,
+ \\ VAL06 = -2,
+ \\ VAL07 = -3,
+ \\ VAL08 = -4,
+ \\ VAL09 = -3,
+ \\ VAL10 = -1000012000,
+ \\ VAL11 = -1000161000,
+ \\ VAL12 = -1000174001,
+ \\ VAL13 = -3,
+ \\ VAL14 = -1000012000,
+ \\ VAL15 = -1000161000,
+ \\ VAL16 = -3,
+ \\ VAL17 = 1000011998,
+ \\ VAL18 = 1152921504606846976,
+ \\ VAL19 = 3458764513820540927,
+ \\ VAL20 = 6917529027641081854,
+ \\ VAL21 = 6917529027641081853,
+ \\ VAL22 = 0,
+ \\ VAL23 = -1,
+ \\};
+ );
+
cases.add("for loop with var init but empty body",
\\void foo(void) {
\\ for (int x = 0; x < 10; x++);
From c5509a07cacfea16b4fb3c8d552a33083b713697 Mon Sep 17 00:00:00 2001
From: Wink Saville
Date: Mon, 24 Sep 2018 09:33:45 -0700
Subject: [PATCH 030/127] Ignore class-memaccess error for gcc 8 and above
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On Arch Linux the current default compiler is gcc 8.2.1 and this change
is needed to ignore the following errors:
In file included from /home/wink/local/include/llvm/ADT/STLExtras.h:21,
from /home/wink/local/include/llvm/ADT/StringRef.h:13,
from /home/wink/local/include/llvm/ADT/StringMap.h:17,
from /home/wink/local/include/llvm/Support/Host.h:17,
from /home/wink/local/include/llvm/ADT/Hashing.h:49,
from /home/wink/local/include/llvm/ADT/ArrayRef.h:13,
from /home/wink/local/include/llvm/ADT/APFloat.h:21,
from /home/wink/local/include/clang/AST/APValue.h:18,
from /home/wink/local/include/clang/AST/Decl.h:17,
from /home/wink/local/include/clang/AST/ASTTypeTraits.h:20,
from /home/wink/local/include/clang/AST/ASTContext.h:18,
from /home/wink/local/include/clang/Frontend/ASTUnit.h:18,
from /home/wink/prgs/ziglang/zig/src/translate_c.cpp:18:
/home/wink/local/include/llvm/ADT/SmallVector.h: In instantiation of ‘void llvm::SmallVectorTemplateBase::push_back(const T&) [with T = std::pair]’:
/home/wink/local/include/llvm/Support/Allocator.h:249:33: required from ‘void* llvm::BumpPtrAllocatorImpl::Allocate(size_t, size_t) [with AllocatorT = llvm::MallocAllocator; long unsigned int SlabSize = 4096; long unsigned int SizeThreshold = 4096; size_t = long unsigned int]’
/home/wink/local/include/clang/AST/ASTContext.h:659:42: required from here
/home/wink/local/include/llvm/ADT/SmallVector.h:313:11: error: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct std::pair’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Werror=class-memaccess]
memcpy(this->end(), &Elt, sizeof(T));
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8.2.1/utility:70,
from /home/wink/local/include/llvm/Support/type_traits.h:19,
from /home/wink/local/include/llvm/Support/Casting.h:19,
from /home/wink/local/include/clang/Basic/LLVM.h:22,
from /home/wink/local/include/clang/AST/APValue.h:17,
from /home/wink/local/include/clang/AST/Decl.h:17,
from /home/wink/local/include/clang/AST/ASTTypeTraits.h:20,
from /home/wink/local/include/clang/AST/ASTContext.h:18,
from /home/wink/local/include/clang/Frontend/ASTUnit.h:18,
from /home/wink/prgs/ziglang/zig/src/translate_c.cpp:18:
/usr/include/c++/8.2.1/bits/stl_pair.h:198:12: note: ‘struct std::pair’ declared here
struct pair
^~~~
---
src/translate_c.cpp | 9 +++++++++
src/zig_llvm.cpp | 9 +++++++++
2 files changed, 18 insertions(+)
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index fd13adb8f6..37d5b722c3 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -15,10 +15,19 @@
#include "parser.hpp"
+#if __GNUC__ >= 8
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+
#include
#include
#include
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+
#include
using namespace clang;
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index ad8edb4cda..8e9fe65d47 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -15,6 +15,11 @@
#include "zig_llvm.h"
+#if __GNUC__ >= 8
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+
#include
#include
#include
@@ -42,6 +47,10 @@
#include
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+
#include
#include
From 422269ea6e49409464fd1fd00212fc7f7681a5e0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 13:08:21 -0400
Subject: [PATCH 031/127] minor langref improvements
---
doc/langref.html.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 40af140c83..4e49db72be 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -393,7 +393,7 @@ pub fn main() void {
| {#syntax#}f16{#endsyntax#} |
- float |
+ _Float16 |
16-bit floating point (10-bit mantissa) IEEE-754-2008 binary16 |
@@ -408,7 +408,7 @@ pub fn main() void {
| {#syntax#}f128{#endsyntax#} |
- (none) |
+ _Float128 |
128-bit floating point (112-bit mantissa) IEEE-754-2008 binary128 |
@@ -480,7 +480,7 @@ pub fn main() void {
- {#see_also|Optionals#}
+ {#see_also|Optionals|undefined#}
{#header_close#}
{#header_open|String Literals#}
{#code_begin|test#}
From 32c91ad892f5dc0138828aea19b3c0e2b062d168 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 14:37:55 -0400
Subject: [PATCH 032/127] fix comptime bitwise operations with negative values
closes #1387
closes #1529
---
src/bigint.cpp | 2 +-
test/cases/eval.zig | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/bigint.cpp b/src/bigint.cpp
index bf18b9a1bf..2737057f97 100644
--- a/src/bigint.cpp
+++ b/src/bigint.cpp
@@ -50,7 +50,7 @@ size_t bigint_bits_needed(const BigInt *op) {
size_t full_bits = op->digit_count * 64;
size_t leading_zero_count = bigint_clz(op, full_bits);
size_t bits_needed = full_bits - leading_zero_count;
- return bits_needed + op->is_negative;
+ return bits_needed;
}
static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) {
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index e0c998e961..08c02f1843 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -737,3 +737,16 @@ test "slice bounds in comptime concatenation" {
assert(str2.len == 1);
assert(std.mem.eql(u8, str2, "1"));
}
+
+test "comptime bitwise operators" {
+ comptime {
+ assert(3 & 1 == 1);
+ assert(3 & -1 == 3);
+ assert(-3 & -1 == -3);
+ assert(3 | -1 == -1);
+ assert(-3 | -1 == -1);
+ assert(3 ^ -1 == -4);
+ assert(~i8(-1) == 0);
+ assert(~i128(-1) == 0);
+ }
+}
From 877036e7ef37432579233347b5b3cfce66040f83 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 15:13:38 -0400
Subject: [PATCH 033/127] fix translate-c test expecting incorrect C ABI on
windows
---
test/translate_c.zig | 110 ++++++++++++++++++++++---------------------
1 file changed, 57 insertions(+), 53 deletions(-)
diff --git a/test/translate_c.zig b/test/translate_c.zig
index f6ce742fcd..9d8c7d9f63 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1,59 +1,63 @@
const tests = @import("tests.zig");
+const builtin = @import("builtin");
pub fn addCases(cases: *tests.TranslateCContext) void {
- cases.add("negative enum init values",
- \\enum EnumWithInits {
- \\ VAL01 = 0,
- \\ VAL02 = 1,
- \\ VAL03 = 2,
- \\ VAL04 = 3,
- \\ VAL05 = -1,
- \\ VAL06 = -2,
- \\ VAL07 = -3,
- \\ VAL08 = -4,
- \\ VAL09 = VAL02 + VAL08,
- \\ VAL10 = -1000012000,
- \\ VAL11 = -1000161000,
- \\ VAL12 = -1000174001,
- \\ VAL13 = VAL09,
- \\ VAL14 = VAL10,
- \\ VAL15 = VAL11,
- \\ VAL16 = VAL13,
- \\ VAL17 = (VAL16 - VAL10 + 1),
- \\ VAL18 = 0x1000000000000000L,
- \\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
- \\ VAL20 = VAL19 + VAL19,
- \\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
- \\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
- \\ VAL23 = 0xFFFFFFFFFFFFFFFF,
- \\};
- ,
- \\pub const enum_EnumWithInits = extern enum(c_longlong) {
- \\ VAL01 = 0,
- \\ VAL02 = 1,
- \\ VAL03 = 2,
- \\ VAL04 = 3,
- \\ VAL05 = -1,
- \\ VAL06 = -2,
- \\ VAL07 = -3,
- \\ VAL08 = -4,
- \\ VAL09 = -3,
- \\ VAL10 = -1000012000,
- \\ VAL11 = -1000161000,
- \\ VAL12 = -1000174001,
- \\ VAL13 = -3,
- \\ VAL14 = -1000012000,
- \\ VAL15 = -1000161000,
- \\ VAL16 = -3,
- \\ VAL17 = 1000011998,
- \\ VAL18 = 1152921504606846976,
- \\ VAL19 = 3458764513820540927,
- \\ VAL20 = 6917529027641081854,
- \\ VAL21 = 6917529027641081853,
- \\ VAL22 = 0,
- \\ VAL23 = -1,
- \\};
- );
+ if (builtin.os != builtin.Os.windows) {
+ // Windows treats this as an enum with type c_int
+ cases.add("big negative enum init values when C ABI supports long long enums",
+ \\enum EnumWithInits {
+ \\ VAL01 = 0,
+ \\ VAL02 = 1,
+ \\ VAL03 = 2,
+ \\ VAL04 = 3,
+ \\ VAL05 = -1,
+ \\ VAL06 = -2,
+ \\ VAL07 = -3,
+ \\ VAL08 = -4,
+ \\ VAL09 = VAL02 + VAL08,
+ \\ VAL10 = -1000012000,
+ \\ VAL11 = -1000161000,
+ \\ VAL12 = -1000174001,
+ \\ VAL13 = VAL09,
+ \\ VAL14 = VAL10,
+ \\ VAL15 = VAL11,
+ \\ VAL16 = VAL13,
+ \\ VAL17 = (VAL16 - VAL10 + 1),
+ \\ VAL18 = 0x1000000000000000L,
+ \\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
+ \\ VAL20 = VAL19 + VAL19,
+ \\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
+ \\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
+ \\ VAL23 = 0xFFFFFFFFFFFFFFFF,
+ \\};
+ ,
+ \\pub const enum_EnumWithInits = extern enum(c_longlong) {
+ \\ VAL01 = 0,
+ \\ VAL02 = 1,
+ \\ VAL03 = 2,
+ \\ VAL04 = 3,
+ \\ VAL05 = -1,
+ \\ VAL06 = -2,
+ \\ VAL07 = -3,
+ \\ VAL08 = -4,
+ \\ VAL09 = -3,
+ \\ VAL10 = -1000012000,
+ \\ VAL11 = -1000161000,
+ \\ VAL12 = -1000174001,
+ \\ VAL13 = -3,
+ \\ VAL14 = -1000012000,
+ \\ VAL15 = -1000161000,
+ \\ VAL16 = -3,
+ \\ VAL17 = 1000011998,
+ \\ VAL18 = 1152921504606846976,
+ \\ VAL19 = 3458764513820540927,
+ \\ VAL20 = 6917529027641081854,
+ \\ VAL21 = 6917529027641081853,
+ \\ VAL22 = 0,
+ \\ VAL23 = -1,
+ \\};
+ );
+ }
cases.add("for loop with var init but empty body",
\\void foo(void) {
From 4241cd666dbf5117a6c32357c091ca3bc7a0fcd0 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 24 Sep 2018 15:44:45 -0400
Subject: [PATCH 034/127] fix more bigint code paths and add tests
---
src/bigint.cpp | 31 ++++++++++---------------------
test/cases/eval.zig | 4 ++++
2 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/src/bigint.cpp b/src/bigint.cpp
index 2737057f97..8a8d028e82 100644
--- a/src/bigint.cpp
+++ b/src/bigint.cpp
@@ -50,7 +50,7 @@ size_t bigint_bits_needed(const BigInt *op) {
size_t full_bits = op->digit_count * 64;
size_t leading_zero_count = bigint_clz(op, full_bits);
size_t bits_needed = full_bits - leading_zero_count;
- return bits_needed;
+ return bits_needed + op->is_negative;
}
static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) {
@@ -1188,7 +1188,6 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
return bigint_init_bigint(dest, op1);
}
if (op1->is_negative || op2->is_negative) {
- // TODO this code path is untested
size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
BigInt twos_comp_op1 = {0};
@@ -1211,13 +1210,9 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
bigint_normalize(dest);
return;
}
- // TODO this code path is untested
- uint64_t first_digit = dest->data.digit;
dest->digit_count = max(op1->digit_count, op2->digit_count);
dest->data.digits = allocate_nonzero(dest->digit_count);
- dest->data.digits[0] = first_digit;
- size_t i = 1;
- for (; i < dest->digit_count; i += 1) {
+ for (size_t i = 0; i < dest->digit_count; i += 1) {
uint64_t digit = 0;
if (i < op1->digit_count) {
digit |= op1_digits[i];
@@ -1236,7 +1231,6 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
return bigint_init_unsigned(dest, 0);
}
if (op1->is_negative || op2->is_negative) {
- // TODO this code path is untested
size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
BigInt twos_comp_op1 = {0};
@@ -1282,7 +1276,6 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
return bigint_init_bigint(dest, op1);
}
if (op1->is_negative || op2->is_negative) {
- // TODO this code path is untested
size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
BigInt twos_comp_op1 = {0};
@@ -1301,27 +1294,25 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
const uint64_t *op2_digits = bigint_ptr(op2);
assert(op1->digit_count > 0 && op2->digit_count > 0);
- uint64_t first_digit = op1_digits[0] ^ op2_digits[0];
if (op1->digit_count == 1 && op2->digit_count == 1) {
dest->digit_count = 1;
- dest->data.digit = first_digit;
+ dest->data.digit = op1_digits[0] ^ op2_digits[0];
bigint_normalize(dest);
return;
}
- // TODO this code path is untested
dest->digit_count = max(op1->digit_count, op2->digit_count);
dest->data.digits = allocate_nonzero(dest->digit_count);
- dest->data.digits[0] = first_digit;
- size_t i = 1;
+ size_t i = 0;
for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
dest->data.digits[i] = op1_digits[i] ^ op2_digits[i];
}
for (; i < dest->digit_count; i += 1) {
if (i < op1->digit_count) {
dest->data.digits[i] = op1_digits[i];
- }
- if (i < op2->digit_count) {
+ } else if (i < op2->digit_count) {
dest->data.digits[i] = op2_digits[i];
+ } else {
+ zig_unreachable();
}
}
bigint_normalize(dest);
@@ -1485,8 +1476,7 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed
bigint_normalize(dest);
return;
}
- // TODO this code path is untested
- dest->digit_count = bit_count / 64;
+ dest->digit_count = (bit_count + 63) / 64;
assert(dest->digit_count >= op->digit_count);
dest->data.digits = allocate_nonzero(dest->digit_count);
size_t i = 0;
@@ -1496,9 +1486,9 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed
for (; i < dest->digit_count; i += 1) {
dest->data.digits[i] = 0xffffffffffffffffULL;
}
- size_t digit_index = dest->digit_count - (bit_count / 64) - 1;
+ size_t digit_index = dest->digit_count - 1;
size_t digit_bit_index = bit_count % 64;
- if (digit_index < dest->digit_count) {
+ if (digit_bit_index != 0) {
uint64_t mask = (1ULL << digit_bit_index) - 1;
dest->data.digits[digit_index] &= mask;
}
@@ -1555,7 +1545,6 @@ void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base) {
buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit);
return;
}
- // TODO this code path is untested
size_t first_digit_index = buf_len(buf);
BigInt digit_bi = {0};
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index 08c02f1843..2cd7f695e7 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -746,7 +746,11 @@ test "comptime bitwise operators" {
assert(3 | -1 == -1);
assert(-3 | -1 == -1);
assert(3 ^ -1 == -4);
+ assert(-3 ^ -1 == 2);
assert(~i8(-1) == 0);
assert(~i128(-1) == 0);
+ assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
+ assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
+ assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
}
}
From 0e6c18c8207cab5d3946f119a51d62f91c1b9028 Mon Sep 17 00:00:00 2001
From: Wink Saville
Date: Sun, 23 Sep 2018 15:53:52 -0700
Subject: [PATCH 035/127] Remove StrLitKind enum
I was looking at the tokenizer specifically fn testTokenize and the
this statement looked odd:
if (@TagType(Token.Id)(token.id) != @TagType(Token.Id)(expected_token_id)) {
I then saw the TODO and thought I'd remove StrLitKind figuring that
would make testTokenize simpler. It did so I thought I'd prepare this PR.
The tests are still working and stage2 zig seems to work, it compiles and
I was able to use the fmt command.
---
std/zig/ast.zig | 4 ++--
std/zig/parse.zig | 24 ++++++++++++------------
std/zig/tokenizer.zig | 37 +++++++++++--------------------------
3 files changed, 25 insertions(+), 40 deletions(-)
diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index b5b3ce9add..2102da456c 100644
--- a/std/zig/ast.zig
+++ b/std/zig/ast.zig
@@ -211,7 +211,7 @@ pub const Error = union(enum) {
pub const ExpectedToken = struct {
token: TokenIndex,
- expected_id: @TagType(Token.Id),
+ expected_id: Token.Id,
pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void {
const token_name = @tagName(tokens.at(self.token).id);
@@ -221,7 +221,7 @@ pub const Error = union(enum) {
pub const ExpectedCommaOrEnd = struct {
token: TokenIndex,
- end_id: @TagType(Token.Id),
+ end_id: Token.Id,
pub fn render(self: *const ExpectedCommaOrEnd, tokens: *Tree.TokenList, stream: var) !void {
const token_name = @tagName(tokens.at(self.token).id);
diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index 136525e0ad..5941ab6905 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -2846,12 +2846,12 @@ const ContainerKindCtx = struct {
};
const ExpectTokenSave = struct {
- id: @TagType(Token.Id),
+ id: Token.Id,
ptr: *TokenIndex,
};
const OptionalTokenSave = struct {
- id: @TagType(Token.Id),
+ id: Token.Id,
ptr: *?TokenIndex,
};
@@ -3066,9 +3066,9 @@ const State = union(enum) {
Identifier: OptionalCtx,
ErrorTag: **ast.Node,
- IfToken: @TagType(Token.Id),
+ IfToken: Token.Id,
IfTokenSave: ExpectTokenSave,
- ExpectToken: @TagType(Token.Id),
+ ExpectToken: Token.Id,
ExpectTokenSave: ExpectTokenSave,
OptionalTokenSave: OptionalTokenSave,
};
@@ -3243,7 +3243,7 @@ const ExpectCommaOrEndResult = union(enum) {
parse_error: Error,
};
-fn expectCommaOrEnd(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree, end: @TagType(Token.Id)) ExpectCommaOrEndResult {
+fn expectCommaOrEnd(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree, end: Token.Id) ExpectCommaOrEndResult {
const token = nextToken(tok_it, tree);
const token_index = token.index;
const token_ptr = token.ptr;
@@ -3288,7 +3288,7 @@ fn tokenIdToAssignment(id: *const Token.Id) ?ast.Node.InfixOp.Op {
};
}
-fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
+fn tokenIdToUnwrapExpr(id: Token.Id) ?ast.Node.InfixOp.Op {
return switch (id) {
Token.Id.Keyword_catch => ast.Node.InfixOp.Op{ .Catch = null },
Token.Id.Keyword_orelse => ast.Node.InfixOp.Op{ .UnwrapOptional = void{} },
@@ -3296,7 +3296,7 @@ fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
};
}
-fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
+fn tokenIdToComparison(id: Token.Id) ?ast.Node.InfixOp.Op {
return switch (id) {
Token.Id.BangEqual => ast.Node.InfixOp.Op{ .BangEqual = void{} },
Token.Id.EqualEqual => ast.Node.InfixOp.Op{ .EqualEqual = void{} },
@@ -3308,7 +3308,7 @@ fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
};
}
-fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
+fn tokenIdToBitShift(id: Token.Id) ?ast.Node.InfixOp.Op {
return switch (id) {
Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op{ .BitShiftLeft = void{} },
Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op{ .BitShiftRight = void{} },
@@ -3316,7 +3316,7 @@ fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
};
}
-fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
+fn tokenIdToAddition(id: Token.Id) ?ast.Node.InfixOp.Op {
return switch (id) {
Token.Id.Minus => ast.Node.InfixOp.Op{ .Sub = void{} },
Token.Id.MinusPercent => ast.Node.InfixOp.Op{ .SubWrap = void{} },
@@ -3327,7 +3327,7 @@ fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
};
}
-fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
+fn tokenIdToMultiply(id: Token.Id) ?ast.Node.InfixOp.Op {
return switch (id) {
Token.Id.Slash => ast.Node.InfixOp.Op{ .Div = void{} },
Token.Id.Asterisk => ast.Node.InfixOp.Op{ .Mult = void{} },
@@ -3339,7 +3339,7 @@ fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
};
}
-fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
+fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
return switch (id) {
Token.Id.Bang => ast.Node.PrefixOp.Op{ .BoolNot = void{} },
Token.Id.Tilde => ast.Node.PrefixOp.Op{ .BitNot = void{} },
@@ -3374,7 +3374,7 @@ fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: *const OptionalCtx, compti
return node;
}
-fn eatToken(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree, id: @TagType(Token.Id)) ?TokenIndex {
+fn eatToken(tok_it: *ast.Tree.TokenList.Iterator, tree: *ast.Tree, id: Token.Id) ?TokenIndex {
const token = tok_it.peek().?;
if (token.id == id) {
diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig
index 1bb3de4935..b996876200 100644
--- a/std/zig/tokenizer.zig
+++ b/std/zig/tokenizer.zig
@@ -73,17 +73,11 @@ pub const Token = struct {
return null;
}
- /// TODO remove this enum
- const StrLitKind = enum {
- Normal,
- C,
- };
-
- pub const Id = union(enum) {
+ pub const Id = enum {
Invalid,
Identifier,
- StringLiteral: StrLitKind,
- MultilineStringLiteralLine: StrLitKind,
+ StringLiteral,
+ MultilineStringLiteralLine,
CharLiteral,
Eof,
Builtin,
@@ -311,7 +305,7 @@ pub const Tokenizer = struct {
},
'"' => {
state = State.StringLiteral;
- result.id = Token.Id{ .StringLiteral = Token.StrLitKind.Normal };
+ result.id = Token.Id.StringLiteral;
},
'\'' => {
state = State.CharLiteral;
@@ -390,7 +384,7 @@ pub const Tokenizer = struct {
},
'\\' => {
state = State.Backslash;
- result.id = Token.Id{ .MultilineStringLiteralLine = Token.StrLitKind.Normal };
+ result.id = Token.Id.MultilineStringLiteralLine;
},
'{' => {
result.id = Token.Id.LBrace;
@@ -591,11 +585,11 @@ pub const Tokenizer = struct {
State.C => switch (c) {
'\\' => {
state = State.Backslash;
- result.id = Token.Id{ .MultilineStringLiteralLine = Token.StrLitKind.C };
+ result.id = Token.Id.MultilineStringLiteralLine;
},
'"' => {
state = State.StringLiteral;
- result.id = Token.Id{ .StringLiteral = Token.StrLitKind.C };
+ result.id = Token.Id.StringLiteral;
},
'a'...'z', 'A'...'Z', '_', '0'...'9' => {
state = State.Identifier;
@@ -1218,7 +1212,7 @@ test "tokenizer - invalid token characters" {
test "tokenizer - invalid literal/comment characters" {
testTokenize("\"\x00\"", []Token.Id{
- Token.Id{ .StringLiteral = Token.StrLitKind.Normal },
+ Token.Id.StringLiteral,
Token.Id.Invalid,
});
testTokenize("//\x00", []Token.Id{
@@ -1304,7 +1298,7 @@ test "tokenizer - string identifier and builtin fns" {
Token.Id.Equal,
Token.Id.Builtin,
Token.Id.LParen,
- Token.Id{ .StringLiteral = Token.StrLitKind.Normal },
+ Token.Id.StringLiteral,
Token.Id.RParen,
Token.Id.Semicolon,
});
@@ -1344,17 +1338,8 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
var tokenizer = Tokenizer.init(source);
for (expected_tokens) |expected_token_id| {
const token = tokenizer.next();
- if (@TagType(Token.Id)(token.id) != @TagType(Token.Id)(expected_token_id)) {
- std.debug.panic("expected {}, found {}\n", @tagName(@TagType(Token.Id)(expected_token_id)), @tagName(@TagType(Token.Id)(token.id)));
- }
- switch (expected_token_id) {
- Token.Id.StringLiteral => |expected_kind| {
- std.debug.assert(expected_kind == switch (token.id) {
- Token.Id.StringLiteral => |kind| kind,
- else => unreachable,
- });
- },
- else => {},
+ if (token.id != expected_token_id) {
+ std.debug.panic("expected {}, found {}\n", @tagName(expected_token_id), @tagName(token.id));
}
}
const last_token = tokenizer.next();
From eafb8e85725df570056f2be09173449f802b90fc Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Sep 2018 10:45:11 -0400
Subject: [PATCH 036/127] fix self reference through fn ptr field crash
closes #1208
---
src/analyze.cpp | 2 +-
test/cases/misc.zig | 15 +++++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index b47f9e9b9c..ca80958887 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1184,7 +1184,7 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
gen_param_info->src_index = i;
gen_param_info->gen_index = SIZE_MAX;
- if ((err = ensure_complete_type(g, type_entry)))
+ if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid;
if (is_c_abi)
diff --git a/test/cases/misc.zig b/test/cases/misc.zig
index 4343cb3b90..572cee5419 100644
--- a/test/cases/misc.zig
+++ b/test/cases/misc.zig
@@ -699,3 +699,18 @@ test "equality compare fn ptrs" {
var a = emptyFn;
assert(a == a);
}
+
+test "self reference through fn ptr field" {
+ const S = struct {
+ const A = struct {
+ f: fn (A) u8,
+ };
+
+ fn foo(a: A) u8 {
+ return 12;
+ }
+ };
+ var a: S.A = undefined;
+ a.f = S.foo;
+ assert(a.f(a) == 12);
+}
From 839492d0e82e5d7b2a5cee54acb9e64b414e9817 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Sep 2018 12:03:09 -0400
Subject: [PATCH 037/127] fix not syntax highlighting builtin module
---
doc/docgen.zig | 24 +++++++++++++++---------
doc/langref.html.in | 2 +-
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/doc/docgen.zig b/doc/docgen.zig
index b5cf2ca87b..cbfd67c740 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -295,7 +295,7 @@ const Link = struct {
const Node = union(enum) {
Content: []const u8,
Nav,
- Builtin,
+ Builtin: Token,
HeaderOpen: HeaderOpen,
SeeAlso: []const SeeAlsoItem,
Code: Code,
@@ -355,7 +355,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
try nodes.append(Node.Nav);
} else if (mem.eql(u8, tag_name, "builtin")) {
_ = try eatToken(tokenizer, Token.Id.BracketClose);
- try nodes.append(Node.Builtin);
+ try nodes.append(Node{ .Builtin = tag_token });
} else if (mem.eql(u8, tag_name, "header_open")) {
_ = try eatToken(tokenizer, Token.Id.Separator);
const content_token = try eatToken(tokenizer, Token.Id.TagContent);
@@ -718,8 +718,7 @@ fn isType(name: []const u8) bool {
return false;
}
-fn tokenizeAndPrint(allocator: *mem.Allocator, docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
- const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
+fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Token, raw_src: []const u8) !void {
const src = mem.trim(u8, raw_src, " \n");
try out.write("");
var tokenizer = std.zig.Tokenizer.init(src);
@@ -928,13 +927,18 @@ fn tokenizeAndPrint(allocator: *mem.Allocator, docgen_tokenizer: *Tokenizer, out
try out.write("");
}
+fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
+ const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
+ return tokenizeAndPrintRaw(docgen_tokenizer, out, source_token, raw_src);
+}
+
fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {
var code_progress_index: usize = 0;
var env_map = try os.getEnvMap(allocator);
try env_map.set("ZIG_DEBUG_COLOR", "1");
- const builtin_code = try escapeHtml(allocator, try getBuiltinCode(allocator, &env_map, zig_exe));
+ const builtin_code = try getBuiltinCode(allocator, &env_map, zig_exe);
for (toc.nodes) |node| {
switch (node) {
@@ -950,8 +954,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
Node.Nav => {
try out.write(toc.toc);
},
- Node.Builtin => {
- try out.print("{}
", builtin_code);
+ Node.Builtin => |tok| {
+ try out.write("");
+ try tokenizeAndPrintRaw(tokenizer, out, tok, builtin_code);
+ try out.write("");
},
Node.HeaderOpen => |info| {
try out.print("{}\n", info.n, info.url, info.name, info.n);
@@ -968,7 +974,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try out.write("\n");
},
Node.Syntax => |content_tok| {
- try tokenizeAndPrint(allocator, tokenizer, out, content_tok);
+ try tokenizeAndPrint(tokenizer, out, content_tok);
},
Node.Code => |code| {
code_progress_index += 1;
@@ -980,7 +986,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try out.print("{}.zig
", code.name);
}
try out.write("");
- try tokenizeAndPrint(allocator, tokenizer, out, code.source_token);
+ try tokenizeAndPrint(tokenizer, out, code.source_token);
try out.write("");
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 4e49db72be..dc307255c7 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1963,7 +1963,7 @@ test "linked list" {
that variable.
If the struct is in the {#syntax#}return{#endsyntax#} expression, it gets named after
the function it is returning from, with the parameter values serialized.
- Otherwise, the struct gets a same such as {#syntax#}(anonymous struct at file.zig:7:38){#endsyntax#}.
+ Otherwise, the struct gets a name such as (anonymous struct at file.zig:7:38).
{#code_begin|exe|struct_name#}
const std = @import("std");
From 2e562a5f366aabefd34a4191b2cd0b5e72d3d089 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 25 Sep 2018 12:03:39 -0400
Subject: [PATCH 038/127] fix crash on runtime index into slice of comptime
type
closes #1435
---
src/analyze.cpp | 7 +++++--
src/ir.cpp | 6 ++++++
test/compile_errors.zig | 16 ++++++++++++++++
3 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index ca80958887..650f5b6b11 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1187,8 +1187,11 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid;
- if (is_c_abi)
+ if (is_c_abi) {
+ if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
+ return g->builtin_types.entry_invalid;
continue;
+ }
if (type_has_bits(type_entry)) {
ZigType *gen_type;
@@ -4464,7 +4467,7 @@ bool handle_is_ptr(ZigType *type_entry) {
return type_has_bits(type_entry->data.maybe.child_type) &&
!type_is_codegen_pointer(type_entry->data.maybe.child_type);
case ZigTypeIdUnion:
- assert(type_entry->data.unionation.complete);
+ assert(type_entry->data.unionation.zero_bits_known);
if (type_entry->data.unionation.gen_field_count == 0)
return false;
if (!type_has_bits(type_entry))
diff --git a/src/ir.cpp b/src/ir.cpp
index 95172e2b59..33d42cfc5f 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -14640,6 +14640,12 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
} else {
// runtime known element index
+ if (type_requires_comptime(return_type)) {
+ ir_add_error(ira, elem_index,
+ buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known",
+ buf_ptr(&return_type->data.pointer.child_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
if (ptr_align < abi_align) {
if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align);
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 5d9fb84c71..d5d0cb38f2 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,22 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "runtime index into comptime type slice",
+ \\const Struct = struct {
+ \\ a: u32,
+ \\};
+ \\fn getIndex() usize {
+ \\ return 2;
+ \\}
+ \\export fn entry() void {
+ \\ const index = getIndex();
+ \\ const field = @typeInfo(Struct).Struct.fields[index];
+ \\}
+ ,
+ ".tmp_source.zig:9:51: error: values of type 'StructField' must be comptime known, but index value is runtime known",
+ );
+
cases.add(
"compile log statement inside function which must be comptime evaluated",
\\fn Foo(comptime T: type) type {
From 7b204649e3af348a7831837d5a36219733b505ca Mon Sep 17 00:00:00 2001
From: Jay Weisskopf
Date: Tue, 25 Sep 2018 20:13:02 -0400
Subject: [PATCH 039/127] stage1: Added `zig help` to show usage on stdout
This will make it easier to do things like `zig help | grep something`.
Invalid arguments will now display a short notice for `zig help`
instead of showing the full usage information. This will make it easier
to see the actual error.
---
src/main.cpp | 74 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 46 insertions(+), 28 deletions(-)
diff --git a/src/main.cpp b/src/main.cpp
index 95fba8d59e..cdb68ec529 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,14 +16,22 @@
#include
-static int usage(const char *arg0) {
- fprintf(stderr, "Usage: %s [command] [options]\n"
+static int print_error_usage(const char *arg0) {
+ fprintf(stderr, "See `%s help` for detailed usage information\n", arg0);
+ return EXIT_FAILURE;
+}
+
+static int print_full_usage(const char *arg0) {
+ fprintf(stdout,
+ "Usage: %s [command] [options]\n"
+ "\n"
"Commands:\n"
" build build project from build.zig\n"
" build-exe [source] create executable from source or object files\n"
" build-lib [source] create library from source or object files\n"
" build-obj [source] create object from source or assembly\n"
" builtin show the source code of that @import(\"builtin\")\n"
+ " help show this usage information\n"
" id print the base64-encoded compiler id\n"
" init-exe initialize a `zig build` application in the cwd\n"
" init-lib initialize a `zig build` library in the cwd\n"
@@ -33,6 +41,7 @@ static int usage(const char *arg0) {
" test [source] create and run a test build\n"
" version print version number and exit\n"
" zen print zen of zig and exit\n"
+ "\n"
"Compile Options:\n"
" --assembly [source] add assembly file to build\n"
" --cache-dir [path] override the cache directory\n"
@@ -63,6 +72,7 @@ static int usage(const char *arg0) {
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mllvm [arg] forward an arg to LLVM's option processing\n"
+ "\n"
"Link Options:\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
@@ -87,13 +97,14 @@ static int usage(const char *arg0) {
" --ver-major [ver] dynamic library semver major version\n"
" --ver-minor [ver] dynamic library semver minor version\n"
" --ver-patch [ver] dynamic library semver patch version\n"
+ "\n"
"Test Options:\n"
" --test-filter [text] skip tests that do not match filter\n"
" --test-name-prefix [text] add prefix to all tests\n"
" --test-cmd [arg] specify test execution command one arg at a time\n"
" --test-cmd-bin appends test binary path to test cmd args\n"
, arg0);
- return EXIT_FAILURE;
+ return EXIT_SUCCESS;
}
static const char *ZIG_ZEN = "\n"
@@ -144,15 +155,16 @@ static int print_target_list(FILE *f) {
}
enum Cmd {
- CmdInvalid,
+ CmdNone,
CmdBuild,
CmdBuiltin,
+ CmdHelp,
CmdRun,
+ CmdTargets,
CmdTest,
+ CmdTranslateC,
CmdVersion,
CmdZen,
- CmdTranslateC,
- CmdTargets,
};
static const char *default_zig_cache_name = "zig-cache";
@@ -251,7 +263,7 @@ int main(int argc, char **argv) {
if (init_kind != InitKindNone) {
if (argc >= 3) {
fprintf(stderr, "Unexpected extra argument: %s\n", argv[2]);
- return usage(arg0);
+ return print_error_usage(arg0);
}
Buf *cmd_template_path = buf_alloc();
os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);
@@ -326,7 +338,7 @@ int main(int argc, char **argv) {
}
}
- Cmd cmd = CmdInvalid;
+ Cmd cmd = CmdNone;
EmitFileType emit_file_type = EmitFileTypeBinary;
const char *in_file = nullptr;
const char *out_file = nullptr;
@@ -547,7 +559,7 @@ int main(int argc, char **argv) {
} else if (strcmp(arg, "--pkg-begin") == 0) {
if (i + 2 >= argc) {
fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
CliPkg *new_cur_pkg = allocate(1);
i += 1;
@@ -565,7 +577,7 @@ int main(int argc, char **argv) {
cur_pkg = cur_pkg->parent;
} else if (i + 1 >= argc) {
fprintf(stderr, "Expected another argument after %s\n", arg);
- return usage(arg0);
+ return print_error_usage(arg0);
} else {
i += 1;
if (strcmp(arg, "--output") == 0) {
@@ -581,7 +593,7 @@ int main(int argc, char **argv) {
color = ErrColorOff;
} else {
fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
} else if (strcmp(arg, "--cache") == 0) {
if (strcmp(argv[i], "auto") == 0) {
@@ -592,7 +604,7 @@ int main(int argc, char **argv) {
enable_cache = CacheOptOff;
} else {
fprintf(stderr, "--cache options are 'auto', 'on', or 'off'\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
} else if (strcmp(arg, "--emit") == 0) {
if (strcmp(argv[i], "asm") == 0) {
@@ -603,7 +615,7 @@ int main(int argc, char **argv) {
emit_file_type = EmitFileTypeLLVMIr;
} else {
fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
} else if (strcmp(arg, "--name") == 0) {
out_name = argv[i];
@@ -672,10 +684,10 @@ int main(int argc, char **argv) {
test_exec_args.append(argv[i]);
} else {
fprintf(stderr, "Invalid argument: %s\n", arg);
- return usage(arg0);
+ return print_error_usage(arg0);
}
}
- } else if (cmd == CmdInvalid) {
+ } else if (cmd == CmdNone) {
if (strcmp(arg, "build-exe") == 0) {
cmd = CmdBuild;
out_type = OutTypeExe;
@@ -685,6 +697,8 @@ int main(int argc, char **argv) {
} else if (strcmp(arg, "build-lib") == 0) {
cmd = CmdBuild;
out_type = OutTypeLib;
+ } else if (strcmp(arg, "help") == 0) {
+ cmd = CmdHelp;
} else if (strcmp(arg, "run") == 0) {
cmd = CmdRun;
out_type = OutTypeExe;
@@ -703,7 +717,7 @@ int main(int argc, char **argv) {
cmd = CmdBuiltin;
} else {
fprintf(stderr, "Unrecognized command: %s\n", arg);
- return usage(arg0);
+ return print_error_usage(arg0);
}
} else {
switch (cmd) {
@@ -719,16 +733,17 @@ int main(int argc, char **argv) {
}
} else {
fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
- return usage(arg0);
+ return print_error_usage(arg0);
}
break;
case CmdBuiltin:
+ case CmdHelp:
case CmdVersion:
case CmdZen:
case CmdTargets:
fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
- return usage(arg0);
- case CmdInvalid:
+ return print_error_usage(arg0);
+ case CmdNone:
zig_unreachable();
}
}
@@ -751,19 +766,19 @@ int main(int argc, char **argv) {
if (target_arch) {
if (parse_target_arch(target_arch, &target->arch)) {
fprintf(stderr, "invalid --target-arch argument\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
}
if (target_os) {
if (parse_target_os(target_os, &target->os)) {
fprintf(stderr, "invalid --target-os argument\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
}
if (target_environ) {
if (parse_target_environ(target_environ, &target->env_type)) {
fprintf(stderr, "invalid --target-environ argument\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
}
}
@@ -785,13 +800,13 @@ int main(int argc, char **argv) {
{
if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
- return usage(arg0);
+ return print_error_usage(arg0);
} else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
fprintf(stderr, "Expected source file argument.\n");
- return usage(arg0);
+ return print_error_usage(arg0);
} else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
@@ -820,7 +835,7 @@ int main(int argc, char **argv) {
if (need_name && buf_out_name == nullptr) {
fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
- return usage(arg0);
+ return print_error_usage(arg0);
}
Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
@@ -1012,6 +1027,8 @@ int main(int argc, char **argv) {
zig_unreachable();
}
}
+ case CmdHelp:
+ return print_full_usage(arg0);
case CmdVersion:
printf("%s\n", ZIG_VERSION_STRING);
return EXIT_SUCCESS;
@@ -1020,7 +1037,8 @@ int main(int argc, char **argv) {
return EXIT_SUCCESS;
case CmdTargets:
return print_target_list(stdout);
- case CmdInvalid:
- return usage(arg0);
+ case CmdNone:
+ fprintf(stderr, "Zig programming language\n");
+ return print_error_usage(arg0);
}
}
From 9485043b3c445a3153e61c0bbc908486134d564a Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Sep 2018 11:06:09 -0400
Subject: [PATCH 040/127] fix implicit casting to *c_void
closes #1588
also some small std lib changes regarding posix sockets
and one doc typo fix
---
doc/langref.html.in | 2 +-
src/ir.cpp | 196 +++++++++++++++++++++++-----------------
std/event/tcp.zig | 50 +++++++++-
std/os/index.zig | 4 +-
std/os/linux/index.zig | 10 +-
test/cases/cast.zig | 10 ++
test/compile_errors.zig | 12 +++
7 files changed, 196 insertions(+), 88 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index dc307255c7..bc7bbf0cbb 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -587,7 +587,7 @@ const c_string_literal =
;
{#code_end#}
- In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const char{#endsyntax#} and
+ In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const u8{#endsyntax#} and
has a terminating null byte.
{#see_also|@embedFile#}
diff --git a/src/ir.cpp b/src/ir.cpp
index 33d42cfc5f..022909d184 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -155,6 +155,8 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val);
+static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
+ ZigType *dest_type, IrInstruction *dest_type_src);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -8573,17 +8575,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
return result;
}
- // *T and [*]T can always cast to *c_void
- if (wanted_type->id == ZigTypeIdPointer &&
- wanted_type->data.pointer.ptr_len == PtrLenSingle &&
- wanted_type->data.pointer.child_type == g->builtin_types.entry_c_void &&
- actual_type->id == ZigTypeIdPointer &&
- (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
- (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
- {
- return result;
- }
-
// pointer const
if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
@@ -11156,6 +11147,33 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
+ // cast from *T and [*]T to *c_void and ?*c_void
+ // but don't do it if the actual type is a double pointer
+ if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.child_type->id != ZigTypeIdPointer) {
+ ZigType *dest_ptr_type = nullptr;
+ if (wanted_type->id == ZigTypeIdPointer &&
+ wanted_type->data.pointer.ptr_len == PtrLenSingle &&
+ wanted_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void)
+ {
+ dest_ptr_type = wanted_type;
+ } else if (wanted_type->id == ZigTypeIdOptional &&
+ wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
+ wanted_type->data.maybe.child_type->data.pointer.ptr_len == PtrLenSingle &&
+ wanted_type->data.maybe.child_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void)
+ {
+ dest_ptr_type = wanted_type->data.maybe.child_type;
+ }
+ if (dest_ptr_type != nullptr &&
+ (!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) &&
+ (!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) &&
+ actual_type->data.pointer.bit_offset == dest_ptr_type->data.pointer.bit_offset &&
+ actual_type->data.pointer.unaligned_bit_count == dest_ptr_type->data.pointer.unaligned_bit_count &&
+ get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
+ {
+ return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);
+ }
+ }
+
// cast from T to *T where T is zero bits
if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
@@ -20234,9 +20252,91 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
return result;
}
-static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
+static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
+ ZigType *dest_type, IrInstruction *dest_type_src)
+{
Error err;
+ ZigType *src_type = ptr->value.type;
+ assert(!type_is_invalid(src_type));
+
+ // We have a check for zero bits later so we use get_src_ptr_type to
+ // validate src_type and dest_type.
+
+ if (get_src_ptr_type(src_type) == nullptr) {
+ ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (get_src_ptr_type(dest_type) == nullptr) {
+ ir_add_error(ira, dest_type_src,
+ buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) {
+ ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (instr_is_comptime(ptr)) {
+ ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,
+ dest_type);
+ copy_const_val(&result->value, val, false);
+ result->value.type = dest_type;
+ return result;
+ }
+
+ uint32_t src_align_bytes;
+ if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
+ return ira->codegen->invalid_instruction;
+
+ uint32_t dest_align_bytes;
+ if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
+ return ira->codegen->invalid_instruction;
+
+ if (dest_align_bytes > src_align_bytes) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
+ add_error_note(ira->codegen, msg, ptr->source_node,
+ buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));
+ add_error_note(ira->codegen, msg, dest_type_src->source_node,
+ buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, nullptr, ptr);
+ casted_ptr->value.type = dest_type;
+
+ if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr,
+ buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
+ buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
+ add_error_note(ira->codegen, msg, ptr->source_node,
+ buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name)));
+ add_error_note(ira->codegen, msg, dest_type_src->source_node,
+ buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ // Keep the bigger alignment, it can only help-
+ // unless the target is zero bits.
+ IrInstruction *result;
+ if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
+ result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
+ if (type_is_invalid(result->value.type))
+ return ira->codegen->invalid_instruction;
+ } else {
+ result = casted_ptr;
+ }
+ return result;
+}
+
+static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
IrInstruction *dest_type_value = instruction->dest_type->other;
ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
if (type_is_invalid(dest_type))
@@ -20247,78 +20347,10 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
if (type_is_invalid(src_type))
return ira->codegen->builtin_types.entry_invalid;
- // We have a check for zero bits later so we use get_src_ptr_type to
- // validate src_type and dest_type.
-
- if (get_src_ptr_type(src_type) == nullptr) {
- ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
- }
-
- if (get_src_ptr_type(dest_type) == nullptr) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
- }
-
- if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) {
- ir_add_error(ira, &instruction->base, buf_sprintf("cast discards const qualifier"));
- return ira->codegen->builtin_types.entry_invalid;
- }
-
- if (instr_is_comptime(ptr)) {
- ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
- if (!val)
- return ira->codegen->builtin_types.entry_invalid;
-
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- copy_const_val(out_val, val, false);
- out_val->type = dest_type;
- return dest_type;
- }
-
- uint32_t src_align_bytes;
- if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
+ IrInstruction *result = ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
+ if (type_is_invalid(result->value.type))
return ira->codegen->builtin_types.entry_invalid;
- uint32_t dest_align_bytes;
- if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
- return ira->codegen->builtin_types.entry_invalid;
-
- if (dest_align_bytes > src_align_bytes) {
- ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));
- add_error_note(ira->codegen, msg, ptr->source_node,
- buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));
- add_error_note(ira->codegen, msg, dest_type_value->source_node,
- buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes));
- return ira->codegen->builtin_types.entry_invalid;
- }
-
- IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, ptr);
- casted_ptr->value.type = dest_type;
-
- if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
- ErrorMsg *msg = ir_add_error(ira, &instruction->base,
- buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
- buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
- add_error_note(ira->codegen, msg, ptr->source_node,
- buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name)));
- add_error_note(ira->codegen, msg, dest_type_value->source_node,
- buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
- }
-
- // Keep the bigger alignment, it can only help-
- // unless the target is zero bits.
- IrInstruction *result;
- if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
- result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- } else {
- result = casted_ptr;
- }
ir_link_new_instruction(result, &instruction->base);
return result->value.type;
}
diff --git a/std/event/tcp.zig b/std/event/tcp.zig
index 5715e46a62..c1e6e891cd 100644
--- a/std/event/tcp.zig
+++ b/std/event/tcp.zig
@@ -110,13 +110,61 @@ pub const Server = struct {
}
};
+pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {
+ const sockfd = try std.os.posixSocket(
+ posix.AF_UNIX,
+ posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK,
+ 0,
+ );
+ errdefer std.os.close(sockfd);
+
+ var sock_addr = posix.sockaddr{
+ .un = posix.sockaddr_un{
+ .family = posix.AF_UNIX,
+ .path = undefined,
+ },
+ };
+
+ if (path.len > @typeOf(sock_addr.un.path).len) return error.NameTooLong;
+ mem.copy(u8, sock_addr.un.path[0..], path);
+ const size = @intCast(u32, @sizeOf(posix.sa_family_t) + path.len);
+ try std.os.posixConnectAsync(sockfd, &sock_addr, size);
+ try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
+ try std.os.posixGetSockOptConnectError(sockfd);
+
+ return sockfd;
+}
+
+pub async fn socketRead(loop: *std.event.Loop, fd: i32, buffer: []u8) !void {
+ while (true) {
+ return std.os.posixRead(fd, buffer) catch |err| switch (err) {
+ error.WouldBlock => {
+ try await try async loop.linuxWaitFd(fd, std.os.posix.EPOLLET | std.os.posix.EPOLLIN);
+ continue;
+ },
+ else => return err,
+ };
+ }
+}
+pub async fn socketWrite(loop: *std.event.Loop, fd: i32, buffer: []const u8) !void {
+ while (true) {
+ return std.os.posixWrite(fd, buffer) catch |err| switch (err) {
+ error.WouldBlock => {
+ try await try async loop.linuxWaitFd(fd, std.os.posix.EPOLLET | std.os.posix.EPOLLOUT);
+ continue;
+ },
+ else => return err,
+ };
+ }
+}
+
pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File {
var address = _address.*; // TODO https://github.com/ziglang/zig/issues/733
const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
errdefer std.os.close(sockfd);
- try std.os.posixConnectAsync(sockfd, &address.os_addr);
+ try std.os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in));
try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
try std.os.posixGetSockOptConnectError(sockfd);
diff --git a/std/os/index.zig b/std/os/index.zig
index d86ab119df..1ce9bd7278 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -2677,9 +2677,9 @@ pub fn posixConnect(sockfd: i32, sockaddr: *const posix.sockaddr) PosixConnectEr
/// Same as posixConnect except it is for blocking socket file descriptors.
/// It expects to receive EINPROGRESS.
-pub fn posixConnectAsync(sockfd: i32, sockaddr: *const posix.sockaddr) PosixConnectError!void {
+pub fn posixConnectAsync(sockfd: i32, sockaddr: *const c_void, len: u32) PosixConnectError!void {
while (true) {
- const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr));
+ const rc = posix.connect(sockfd, sockaddr, len);
const err = posix.getErrno(rc);
switch (err) {
0, posix.EINPROGRESS => return,
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index c369921e14..6323c89dda 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -1094,6 +1094,7 @@ pub const in_port_t = u16;
pub const sa_family_t = u16;
pub const socklen_t = u32;
+/// This intentionally only has ip4 and ip6
pub const sockaddr = extern union {
in: sockaddr_in,
in6: sockaddr_in6,
@@ -1114,6 +1115,11 @@ pub const sockaddr_in6 = extern struct {
scope_id: u32,
};
+pub const sockaddr_un = extern struct {
+ family: sa_family_t,
+ path: [108]u8,
+};
+
pub const iovec = extern struct {
iov_base: [*]u8,
iov_len: usize,
@@ -1148,8 +1154,8 @@ pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
}
-pub fn connect(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
- return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len));
+pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
+ return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len);
}
pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
diff --git a/test/cases/cast.zig b/test/cases/cast.zig
index 880ebfb386..92148728a6 100644
--- a/test/cases/cast.zig
+++ b/test/cases/cast.zig
@@ -537,3 +537,13 @@ pub const PFN_void = extern fn (*c_void) void;
fn foobar(func: PFN_void) void {
std.debug.assert(@ptrToInt(func) == @maxValue(usize));
}
+
+test "implicit ptr to *c_void" {
+ var a: u32 = 1;
+ var ptr: *c_void = &a;
+ var b: *u32 = @ptrCast(*u32, ptr);
+ assert(b.* == 1);
+ var ptr2: ?*c_void = &a;
+ var c: *u32 = @ptrCast(*u32, ptr2.?);
+ assert(c.* == 1);
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index d5d0cb38f2..19bb630fb7 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,18 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "don't implicit cast double pointer to *c_void",
+ \\export fn entry() void {
+ \\ var a: u32 = 1;
+ \\ var ptr: *c_void = &a;
+ \\ var b: *u32 = @ptrCast(*u32, ptr);
+ \\ var ptr2: *c_void = &b;
+ \\}
+ ,
+ ".tmp_source.zig:5:26: error: expected type '*c_void', found '**u32'",
+ );
+
cases.add(
"runtime index into comptime type slice",
\\const Struct = struct {
From 631851f8b55b78363c9bc773230d9ee1e7122f5e Mon Sep 17 00:00:00 2001
From: Wink Saville
Date: Tue, 25 Sep 2018 16:27:39 -0700
Subject: [PATCH 041/127] Tweak SYMBOL_CHAR define in tokenizer.cpp
Make it a little clearer what a SYMBOL_CHAR is, use ALPHA instead of
ALPHA_EXCEPT_C and case 'c', which is ALPHA's definition.
---
src/tokenizer.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 84d1d90518..ebe1b07359 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -92,10 +92,9 @@
case 'c'
#define SYMBOL_CHAR \
- ALPHA_EXCEPT_C: \
+ ALPHA: \
case DIGIT: \
- case '_': \
- case 'c'
+ case '_'
#define SYMBOL_START \
ALPHA: \
From dcfd15a7f0ed5159afad47915a11d1dd8315cbe8 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Sep 2018 14:24:55 -0400
Subject: [PATCH 042/127] the last number in a packed ptr is host int bytes
See #1121
---
src/all_types.hpp | 17 +++++------
src/analyze.cpp | 65 ++++++++++++++++++++++++-----------------
src/analyze.hpp | 2 ++
src/ast_render.cpp | 4 +--
src/codegen.cpp | 51 +++++++++++++++++++-------------
src/ir.cpp | 62 +++++++++++++++++++--------------------
src/ir_print.cpp | 2 +-
src/parser.cpp | 4 +--
test/cases/align.zig | 2 +-
test/cases/eval.zig | 8 +++++
test/compile_errors.zig | 2 +-
11 files changed, 124 insertions(+), 95 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 0eaf69ed64..89c117ce82 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -664,7 +664,7 @@ struct AstNodePointerType {
Token *star_token;
AstNode *align_expr;
BigInt *bit_offset_start;
- BigInt *bit_offset_end;
+ BigInt *host_int_bytes;
bool is_const;
bool is_volatile;
AstNode *op_expr;
@@ -1020,8 +1020,8 @@ struct ZigTypePointer {
ZigType *slice_parent;
PtrLen ptr_len;
uint32_t explicit_alignment; // 0 means use ABI alignment
- uint32_t bit_offset;
- uint32_t unaligned_bit_count;
+ uint32_t bit_offset_in_host;
+ uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
bool is_const;
bool is_volatile;
};
@@ -1045,10 +1045,7 @@ struct TypeStructField {
ZigType *type_entry;
size_t src_index;
size_t gen_index;
- // offset from the memory at gen_index
- size_t packed_bits_offset;
- size_t packed_bits_size;
- size_t unaligned_bit_count;
+ uint32_t bit_offset_in_host; // offset from the memory at gen_index
AstNode *decl_node;
};
@@ -1470,8 +1467,8 @@ struct TypeId {
bool is_const;
bool is_volatile;
uint32_t alignment;
- uint32_t bit_offset;
- uint32_t unaligned_bit_count;
+ uint32_t bit_offset_in_host;
+ uint32_t host_int_bytes;
} pointer;
struct {
ZigType *child_type;
@@ -2510,7 +2507,7 @@ struct IrInstructionPtrType {
IrInstruction *align_value;
IrInstruction *child_type;
uint32_t bit_offset_start;
- uint32_t bit_offset_end;
+ uint32_t host_int_bytes;
PtrLen ptr_len;
bool is_const;
bool is_volatile;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 650f5b6b11..e0aa6224e8 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -419,7 +419,7 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
}
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
- bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count)
+ bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)
{
assert(!type_is_invalid(child_type));
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
@@ -430,23 +430,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
byte_alignment = 0;
}
+ if (host_int_bytes != 0) {
+ uint32_t child_type_bits = type_size_bits(g, child_type);
+ if (host_int_bytes * 8 == child_type_bits) {
+ assert(bit_offset_in_host == 0);
+ host_int_bytes = 0;
+ }
+ }
+
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
- if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
+ if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
type_id.data.pointer.is_volatile = is_volatile;
type_id.data.pointer.alignment = byte_alignment;
- type_id.data.pointer.bit_offset = bit_offset;
- type_id.data.pointer.unaligned_bit_count = unaligned_bit_count;
+ type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
+ type_id.data.pointer.host_int_bytes = host_int_bytes;
type_id.data.pointer.ptr_len = ptr_len;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
return existing_entry->value;
} else {
- assert(bit_offset == 0);
+ assert(bit_offset_in_host == 0);
parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
if (*parent_pointer) {
assert((*parent_pointer)->data.pointer.explicit_alignment == 0);
@@ -463,17 +471,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
const char *const_str = is_const ? "const " : "";
const char *volatile_str = is_volatile ? "volatile " : "";
buf_resize(&entry->name, 0);
- if (unaligned_bit_count == 0 && byte_alignment == 0) {
+ if (host_int_bytes == 0 && byte_alignment == 0) {
buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
- } else if (unaligned_bit_count == 0) {
+ } else if (host_int_bytes == 0) {
buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
const_str, volatile_str, buf_ptr(&child_type->name));
} else if (byte_alignment == 0) {
buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
- bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
+ bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
} else {
buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
+ bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
}
assert(child_type->id != ZigTypeIdInvalid);
@@ -481,7 +489,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->zero_bits = !type_has_bits(child_type);
if (!entry->zero_bits) {
- if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 ||
+ if (is_const || is_volatile || host_int_bytes != 0 || byte_alignment != 0 ||
ptr_len != PtrLenSingle)
{
ZigType *peer_type = get_pointer_to_type(g, child_type, false);
@@ -506,8 +514,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->data.pointer.is_const = is_const;
entry->data.pointer.is_volatile = is_volatile;
entry->data.pointer.explicit_alignment = byte_alignment;
- entry->data.pointer.bit_offset = bit_offset;
- entry->data.pointer.unaligned_bit_count = unaligned_bit_count;
+ entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
+ entry->data.pointer.host_int_bytes = host_int_bytes;
if (parent_pointer) {
*parent_pointer = entry;
@@ -2007,12 +2015,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
size_t field_size_in_bits = type_size_bits(g, field_type);
size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;
- type_struct_field->packed_bits_size = field_size_in_bits;
-
if (first_packed_bits_offset_misalign != SIZE_MAX) {
// this field is not byte-aligned; it is part of the previous field with a bit offset
- type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign;
- type_struct_field->unaligned_bit_count = field_size_in_bits;
+ type_struct_field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign;
size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign;
LLVMTypeRef int_type_ref = LLVMIntType((unsigned)(full_bit_count));
@@ -2025,13 +2030,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
}
} else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) {
first_packed_bits_offset_misalign = packed_bits_offset;
- type_struct_field->packed_bits_offset = 0;
- type_struct_field->unaligned_bit_count = field_size_in_bits;
+ type_struct_field->bit_offset_in_host = 0;
} else {
// This is a byte-aligned field (both start and end) in a packed struct.
element_types[gen_field_index] = field_type->type_ref;
- type_struct_field->packed_bits_offset = 0;
- type_struct_field->unaligned_bit_count = 0;
+ type_struct_field->bit_offset_in_host = 0;
gen_field_index += 1;
}
packed_bits_offset = next_packed_bits_offset;
@@ -2124,10 +2127,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
uint64_t debug_align_in_bits;
uint64_t debug_offset_in_bits;
if (packed) {
- debug_size_in_bits = type_struct_field->packed_bits_size;
+ debug_size_in_bits = type_size_bits(g, type_struct_field->type_entry);
debug_align_in_bits = 1;
debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref,
- (unsigned)gen_field_index) + type_struct_field->packed_bits_offset;
+ (unsigned)gen_field_index) + type_struct_field->bit_offset_in_host;
} else {
debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);
@@ -6007,8 +6010,8 @@ uint32_t type_id_hash(TypeId x) {
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
- (((uint32_t)x.data.pointer.bit_offset) ^ (uint32_t)2639019452) +
- (((uint32_t)x.data.pointer.unaligned_bit_count) ^ (uint32_t)529908881);
+ (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
+ (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
case ZigTypeIdArray:
return hash_ptr(x.data.array.child_type) +
((uint32_t)x.data.array.size ^ (uint32_t)2122979968);
@@ -6055,8 +6058,8 @@ bool type_id_eql(TypeId a, TypeId b) {
a.data.pointer.is_const == b.data.pointer.is_const &&
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
a.data.pointer.alignment == b.data.pointer.alignment &&
- a.data.pointer.bit_offset == b.data.pointer.bit_offset &&
- a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count;
+ a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
+ a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
case ZigTypeIdArray:
return a.data.array.child_type == b.data.array.child_type &&
a.data.array.size == b.data.array.size;
@@ -6534,3 +6537,13 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
ty->id == ZigTypeIdUnreachable ||
get_codegen_ptr_type(ty) != nullptr);
}
+
+uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) {
+ assert(struct_type->id == ZigTypeIdStruct);
+ if (struct_type->data.structure.layout != ContainerLayoutPacked) {
+ return 0;
+ }
+ LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
+ return LLVMStoreSizeOfType(g->target_data_ref, field_type);
+}
+
diff --git a/src/analyze.hpp b/src/analyze.hpp
index b04cf6fdfd..fdc979ec9a 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -216,4 +216,6 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
+uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
+
#endif
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 37d4221eef..82c245d03a 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -635,7 +635,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, "align(");
render_node_grouped(ar, node->data.pointer_type.align_expr);
if (node->data.pointer_type.bit_offset_start != nullptr) {
- assert(node->data.pointer_type.bit_offset_end != nullptr);
+ assert(node->data.pointer_type.host_int_bytes != nullptr);
Buf offset_start_buf = BUF_INIT;
buf_resize(&offset_start_buf, 0);
@@ -643,7 +643,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
Buf offset_end_buf = BUF_INIT;
buf_resize(&offset_end_buf, 0);
- bigint_append_buf(&offset_end_buf, node->data.pointer_type.bit_offset_end, 10);
+ bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10);
fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf));
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d4d57d541c..176b7bb08b 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1795,8 +1795,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
return nullptr;
}
- uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
- if (unaligned_bit_count == 0) {
+ uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
+ if (host_int_bytes == 0) {
gen_store(g, value, ptr, ptr_type);
return nullptr;
}
@@ -1804,10 +1804,12 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
bool big_endian = g->is_big_endian;
LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
-
- uint32_t bit_offset = ptr_type->data.pointer.bit_offset;
uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
- uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset;
+ assert(host_bit_count == host_int_bytes * 8);
+ uint32_t size_in_bits = type_size_bits(g, child_type);
+
+ uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host;
+ uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset;
LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref);
@@ -3209,18 +3211,20 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
ZigType *ptr_type = instruction->ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
- uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
- if (unaligned_bit_count == 0)
+ uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
+ if (host_int_bytes == 0)
return get_handle_value(g, ptr, child_type, ptr_type);
bool big_endian = g->is_big_endian;
assert(!handle_is_ptr(child_type));
LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
-
- uint32_t bit_offset = ptr_type->data.pointer.bit_offset;
uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
- uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset;
+ assert(host_bit_count == host_int_bytes * 8);
+ uint32_t size_in_bits = type_size_bits(g, child_type);
+
+ uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host;
+ uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset;
LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
@@ -3276,20 +3280,22 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
array_type->data.array.len, false);
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
}
- if (array_ptr_type->data.pointer.unaligned_bit_count != 0) {
+ if (array_ptr_type->data.pointer.host_int_bytes != 0) {
return array_ptr_ptr;
}
ZigType *child_type = array_type->data.array.child_type;
if (child_type->id == ZigTypeIdStruct &&
child_type->data.structure.layout == ContainerLayoutPacked)
{
- size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
- if (unaligned_bit_count != 0) {
+ ZigType *ptr_type = instruction->base.value.type;
+ size_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
+ if (host_int_bytes != 0) {
+ uint32_t size_in_bits = type_size_bits(g, ptr_type->data.pointer.child_type);
LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
- assert(unaligned_bit_count % 8 == 0);
+ assert(size_in_bits % 8 == 0);
LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
- unaligned_bit_count / 8, false);
+ size_in_bits / 8, false);
LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
LLVMValueRef indices[] = {
byte_offset
@@ -3505,7 +3511,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
return nullptr;
if (struct_ptr_type->id == ZigTypeIdPointer &&
- struct_ptr_type->data.pointer.unaligned_bit_count != 0)
+ struct_ptr_type->data.pointer.host_int_bytes != 0)
{
return struct_ptr;
}
@@ -4671,10 +4677,11 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
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->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count);
+ (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes);
gen_assign_raw(g, field_ptr, ptr_type, value);
}
@@ -5459,15 +5466,16 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
continue;
}
LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]);
+ uint32_t packed_bits_size = type_size_bits(g, field->type_entry);
if (is_big_endian) {
- LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, field->packed_bits_size, false);
+ LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
val = LLVMConstShl(val, shift_amt);
val = LLVMConstOr(val, child_val);
} else {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
val = LLVMConstOr(val, child_val_shifted);
- used_bits += field->packed_bits_size;
+ used_bits += packed_bits_size;
}
}
return val;
@@ -5677,16 +5685,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
}
LLVMValueRef child_val = pack_const_int(g, big_int_type_ref,
&const_val->data.x_struct.fields[i]);
+ uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry);
if (is_big_endian) {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref,
- it_field->packed_bits_size, false);
+ packed_bits_size, false);
val = LLVMConstShl(val, shift_amt);
val = LLVMConstOr(val, child_val);
} else {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
val = LLVMConstOr(val, child_val_shifted);
- used_bits += it_field->packed_bits_size;
+ used_bits += packed_bits_size;
}
}
fields[type_struct_field->gen_index] = val;
diff --git a/src/ir.cpp b/src/ir.cpp
index 022909d184..79b809349c 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1296,7 +1296,7 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru
static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
- IrInstruction *align_value, uint32_t bit_offset_start, uint32_t bit_offset_end)
+ IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes)
{
IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction(irb, scope, source_node);
ptr_type_of_instruction->align_value = align_value;
@@ -1305,7 +1305,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
ptr_type_of_instruction->is_volatile = is_volatile;
ptr_type_of_instruction->ptr_len = ptr_len;
ptr_type_of_instruction->bit_offset_start = bit_offset_start;
- ptr_type_of_instruction->bit_offset_end = bit_offset_end;
+ ptr_type_of_instruction->host_int_bytes = host_int_bytes;
if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
ir_ref_instruction(child_type, irb->current_basic_block);
@@ -5154,26 +5154,26 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start);
}
- uint32_t bit_offset_end = 0;
- if (node->data.pointer_type.bit_offset_end != nullptr) {
- if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_end, 32, false)) {
+ uint32_t host_int_bytes = 0;
+ if (node->data.pointer_type.host_int_bytes != nullptr) {
+ if (!bigint_fits_in_bits(node->data.pointer_type.host_int_bytes, 32, false)) {
Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_end, 10);
+ bigint_append_buf(val_buf, node->data.pointer_type.host_int_bytes, 10);
exec_add_error_node(irb->codegen, irb->exec, node,
- buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));
+ buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf)));
return irb->codegen->invalid_instruction;
}
- bit_offset_end = bigint_as_unsigned(node->data.pointer_type.bit_offset_end);
+ host_int_bytes = bigint_as_unsigned(node->data.pointer_type.host_int_bytes);
}
- if ((bit_offset_start != 0 || bit_offset_end != 0) && bit_offset_start >= bit_offset_end) {
+ if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) {
exec_add_error_node(irb->codegen, irb->exec, node,
- buf_sprintf("bit offset start must be less than bit offset end"));
+ buf_sprintf("bit offset starts after end of host integer"));
return irb->codegen->invalid_instruction;
}
return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,
- ptr_len, align_value, bit_offset_start, bit_offset_end);
+ ptr_len, align_value, bit_offset_start, host_int_bytes);
}
static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
@@ -8600,8 +8600,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
(!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
(!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
- actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
- actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
+ actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
+ actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
{
return result;
@@ -8622,8 +8622,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
}
if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
(!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
- actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset &&
- actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count &&
+ actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
+ actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type))
{
ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
@@ -11166,8 +11166,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (dest_ptr_type != nullptr &&
(!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) &&
(!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) &&
- actual_type->data.pointer.bit_offset == dest_ptr_type->data.pointer.bit_offset &&
- actual_type->data.pointer.unaligned_bit_count == dest_ptr_type->data.pointer.unaligned_bit_count &&
+ actual_type->data.pointer.bit_offset_in_host == dest_ptr_type->data.pointer.bit_offset_in_host &&
+ actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
{
return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);
@@ -14359,7 +14359,7 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
ptr_type->data.pointer.ptr_len,
new_align,
- ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
+ ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
}
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {
@@ -14376,7 +14376,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
ptr_len,
ptr_type->data.pointer.explicit_alignment,
- ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
+ ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
}
static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
@@ -14423,7 +14423,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
return ira->codegen->builtin_types.entry_invalid;
}
ZigType *child_type = array_type->data.array.child_type;
- if (ptr_type->data.pointer.unaligned_bit_count == 0) {
+ if (ptr_type->data.pointer.host_int_bytes == 0) {
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
elem_ptr_instruction->ptr_len,
@@ -14439,7 +14439,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
elem_ptr_instruction->ptr_len,
- 1, (uint32_t)bit_offset, (uint32_t)bit_width);
+ 1, (uint32_t)bit_offset, ptr_type->data.pointer.host_int_bytes);
}
} else if (array_type->id == ZigTypeIdPointer) {
if (array_type->data.pointer.ptr_len == PtrLenSingle) {
@@ -14740,10 +14740,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
if (field) {
bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
- size_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset;
- size_t ptr_unaligned_bit_count = container_ptr->value.type->data.pointer.unaligned_bit_count;
- size_t unaligned_bit_count_for_result_type = (ptr_unaligned_bit_count == 0) ?
- field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry);
+ uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
+ uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes;
+ uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
+ get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes;
if (instr_is_comptime(container_ptr)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
if (!ptr_val)
@@ -14758,8 +14758,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
is_const, is_volatile, PtrLenSingle, align_bytes,
- (uint32_t)(ptr_bit_offset + field->packed_bits_offset),
- (uint32_t)unaligned_bit_count_for_result_type);
+ (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
+ (uint32_t)host_int_bytes_for_result_type);
IrInstruction *result = ir_get_const(ira, source_instr);
ConstExprValue *const_val = &result->value;
const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
@@ -14775,8 +14775,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
PtrLenSingle,
align_bytes,
- (uint32_t)(ptr_bit_offset + field->packed_bits_offset),
- (uint32_t)unaligned_bit_count_for_result_type);
+ (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
+ host_int_bytes_for_result_type);
return result;
} else {
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
@@ -17135,7 +17135,7 @@ static ZigType *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset)))
return ira->codegen->builtin_types.entry_invalid;
- size_t bit_offset = byte_offset * 8 + field->packed_bits_offset;
+ size_t bit_offset = byte_offset * 8 + field->bit_offset_in_host;
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
bigint_init_unsigned(&out_val->data.x_bigint, bit_offset);
return ira->codegen->builtin_types.entry_num_lit_int;
@@ -20758,7 +20758,7 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr
out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,
instruction->is_const, instruction->is_volatile,
instruction->ptr_len, align_bytes,
- instruction->bit_offset_start, instruction->bit_offset_end - instruction->bit_offset_start);
+ instruction->bit_offset_start, instruction->host_int_bytes);
return ira->codegen->builtin_types.entry_type;
}
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index dc756cf492..3bed716756 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1015,7 +1015,7 @@ static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) {
}
const char *const_str = instruction->is_const ? "const " : "";
const char *volatile_str = instruction->is_volatile ? "volatile " : "";
- fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->bit_offset_end,
+ fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes,
const_str, volatile_str);
ir_print_other_instruction(irp, instruction->child_type);
}
diff --git a/src/parser.cpp b/src/parser.cpp
index 8e6076c5e5..c57b1303e7 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1161,10 +1161,10 @@ static AstNode *ast_parse_pointer_type(ParseContext *pc, size_t *token_index, To
*token_index += 1;
Token *bit_offset_start_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
ast_eat_token(pc, token_index, TokenIdColon);
- Token *bit_offset_end_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
+ Token *host_int_bytes_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
node->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start_tok);
- node->data.pointer_type.bit_offset_end = token_bigint(bit_offset_end_tok);
+ node->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes_tok);
}
ast_eat_token(pc, token_index, TokenIdRParen);
token = &pc->tokens->at(*token_index);
diff --git a/test/cases/align.zig b/test/cases/align.zig
index 838935f53c..3dff57feb8 100644
--- a/test/cases/align.zig
+++ b/test/cases/align.zig
@@ -40,7 +40,7 @@ const blah: packed struct {
} = undefined;
test "bit field alignment" {
- assert(@typeOf(&blah.b) == *align(1:3:6) const u3);
+ assert(@typeOf(&blah.b) == *align(1:3:1) const u3);
}
test "default alignment allows unspecified in type syntax" {
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index 2cd7f695e7..408e9b04af 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -754,3 +754,11 @@ test "comptime bitwise operators" {
assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
}
}
+
+test "*align(1) u16 is the same as *align(1:0:2) u16" {
+ comptime {
+ assert(*align(1:0:2) u16 == *align(1) u16);
+ // TODO add parsing support for this syntax
+ //assert(*align(:0:2) u16 == *u16);
+ }
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 19bb630fb7..96d35e4de9 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -3536,7 +3536,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
,
- ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:6) const u3'",
+ ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:1) const u3'",
);
cases.add(
From 589201b10492e2aba06df7860666cef7c6916acc Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Sep 2018 14:54:07 -0400
Subject: [PATCH 043/127] fix variables which are pointers to packed struct
fields
closes #1121
---
src/analyze.cpp | 29 ++++++++++++++++++-----------
test/cases/struct.zig | 13 +++++++++++++
2 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index e0aa6224e8..bd1395c9c2 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -489,20 +489,27 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->zero_bits = !type_has_bits(child_type);
if (!entry->zero_bits) {
- if (is_const || is_volatile || host_int_bytes != 0 || byte_alignment != 0 ||
- ptr_len != PtrLenSingle)
- {
- ZigType *peer_type = get_pointer_to_type(g, child_type, false);
+ if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
+ ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
+ PtrLenSingle, 0, 0, host_int_bytes);
entry->type_ref = peer_type->type_ref;
entry->di_type = peer_type->di_type;
} else {
- entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
-
- uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
- uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref);
- assert(child_type->di_type);
- entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type,
- debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
+ if (host_int_bytes == 0) {
+ entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
+ uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
+ uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref);
+ assert(child_type->di_type);
+ entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type,
+ debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
+ } else {
+ ZigType *host_int_type = get_int_type(g, false, host_int_bytes * 8);
+ entry->type_ref = LLVMPointerType(host_int_type->type_ref, 0);
+ uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, host_int_type->type_ref);
+ uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, host_int_type->type_ref);
+ entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, host_int_type->di_type,
+ debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
+ }
}
} else {
assert(byte_alignment == 0);
diff --git a/test/cases/struct.zig b/test/cases/struct.zig
index 4ca0135444..2e1b4dfbef 100644
--- a/test/cases/struct.zig
+++ b/test/cases/struct.zig
@@ -453,3 +453,16 @@ test "implicit cast packed struct field to const ptr" {
const res = LevelUpMove.toInt(lup.level);
assert(res == 12);
}
+
+test "pointer to packed struct member in a stack variable" {
+ const S = packed struct {
+ a: u2,
+ b: u2,
+ };
+
+ var s = S{ .a = 2, .b = 0 };
+ var b_ptr = &s.b;
+ assert(s.b == 0);
+ b_ptr.* = 2;
+ assert(s.b == 2);
+}
From 1c26c2f4d5c9029fe39cc413f75e547636e42a14 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Sep 2018 16:59:08 -0400
Subject: [PATCH 044/127] fix crash when compile error evaluating return...
...type of inferred error set. closes #1591
---
src/analyze.cpp | 4 +++-
src/ir.cpp | 20 ++++++++++++++++++--
test/compile_errors.zig | 13 +++++++++++++
3 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index bd1395c9c2..ae0d67b2ec 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -673,7 +673,7 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
ZigType *entry = new_type_table_entry(ZigTypeIdErrorUnion);
entry->is_copyable = true;
assert(payload_type->di_type);
- assertNoError(ensure_complete_type(g, payload_type));
+ assert(type_is_complete(payload_type));
buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name));
@@ -1684,6 +1684,8 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
if (fn_proto->auto_err_set) {
ZigType *inferred_err_set_type = get_auto_err_set_type(g, fn_entry);
+ if ((err = type_resolve(g, specified_return_type, ResolveStatusSizeKnown)))
+ return g->builtin_types.entry_invalid;
fn_type_id.return_type = get_error_union_type(g, inferred_err_set_type, specified_return_type);
} else {
fn_type_id.return_type = specified_return_type;
diff --git a/src/ir.cpp b/src/ir.cpp
index 79b809349c..abdb3a24a3 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -9344,9 +9344,15 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
return err_set_type;
} else if (prev_inst->value.type->id == ZigTypeIdErrorUnion) {
- return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type->data.error_union.payload_type);
+ ZigType *payload_type = prev_inst->value.type->data.error_union.payload_type;
+ if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
+ return get_error_union_type(ira->codegen, err_set_type, payload_type);
} else if (expected_type != nullptr && expected_type->id == ZigTypeIdErrorUnion) {
- return get_error_union_type(ira->codegen, err_set_type, expected_type->data.error_union.payload_type);
+ ZigType *payload_type = expected_type->data.error_union.payload_type;
+ if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
+ return get_error_union_type(ira->codegen, err_set_type, payload_type);
} else {
if (prev_inst->value.type->id == ZigTypeIdComptimeInt ||
prev_inst->value.type->id == ZigTypeIdComptimeFloat)
@@ -9359,6 +9365,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
buf_sprintf("unable to make error union out of null literal"));
return ira->codegen->builtin_types.entry_invalid;
} else {
+ if ((err = type_resolve(ira->codegen, prev_inst->value.type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);
}
}
@@ -13053,6 +13061,8 @@ static ZigType *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
static ZigType *ir_analyze_instruction_error_union(IrAnalyze *ira,
IrInstructionErrorUnion *instruction)
{
+ Error err;
+
ZigType *err_set_type = ir_resolve_type(ira, instruction->err_set->other);
if (type_is_invalid(err_set_type))
return ira->codegen->builtin_types.entry_invalid;
@@ -13068,6 +13078,8 @@ static ZigType *ir_analyze_instruction_error_union(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_invalid;
}
+ if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
ZigType *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
@@ -13486,6 +13498,8 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
ZigType *inferred_err_set_type = nullptr;
if (fn_proto_node->data.fn_proto.auto_err_set) {
inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry);
+ if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
} else {
return_type = specified_return_type;
@@ -13713,6 +13727,8 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
return ira->codegen->builtin_types.entry_invalid;
if (fn_proto_node->data.fn_proto.auto_err_set) {
ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn);
+ if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
inst_fn_type_id.return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
} else {
inst_fn_type_id.return_type = specified_return_type;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 96d35e4de9..fb7b536be9 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,19 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "compile error when evaluating return type of inferred error set",
+ \\const Car = struct {
+ \\ foo: *SymbolThatDoesNotExist,
+ \\ pub fn init() !Car {}
+ \\};
+ \\export fn entry() void {
+ \\ const car = Car.init();
+ \\}
+ ,
+ ".tmp_source.zig:2:11: error: use of undeclared identifier 'SymbolThatDoesNotExist'",
+ );
+
cases.add(
"don't implicit cast double pointer to *c_void",
\\export fn entry() void {
From e7d9d00ac8c2bb075d0f67842b58718aececdc09 Mon Sep 17 00:00:00 2001
From: Josh Wolfe
Date: Thu, 27 Sep 2018 00:35:38 -0400
Subject: [PATCH 045/127] overhaul api for getting random integers (#1578)
* rand api overhaul
* no retry limits. instead documented a recommendation
to call int(T) % len directly.
---
std/rand/index.zig | 335 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 268 insertions(+), 67 deletions(-)
diff --git a/std/rand/index.zig b/std/rand/index.zig
index 2cbff049ea..6cad865d1e 100644
--- a/std/rand/index.zig
+++ b/std/rand/index.zig
@@ -5,11 +5,11 @@
// ```
// var buf: [8]u8 = undefined;
// try std.os.getRandomBytes(buf[0..]);
-// const seed = mem.readInt(buf[0..8], u64, builtin.Endian.Little);
+// const seed = mem.readIntLE(u64, buf[0..8]);
//
// var r = DefaultPrng.init(seed);
//
-// const s = r.random.scalar(u64);
+// const s = r.random.int(u64);
// ```
//
// TODO(tiehuis): Benchmark these against other reference implementations.
@@ -35,60 +35,117 @@ pub const Random = struct {
r.fillFn(r, buf);
}
- /// Return a random integer/boolean type.
- pub fn scalar(r: *Random, comptime T: type) T {
- var rand_bytes: [@sizeOf(T)]u8 = undefined;
+ pub fn boolean(r: *Random) bool {
+ return r.int(u1) != 0;
+ }
+
+ /// Returns a random int `i` such that `0 <= i <= @maxValue(T)`.
+ /// `i` is evenly distributed.
+ pub fn int(r: *Random, comptime T: type) T {
+ const UnsignedT = @IntType(false, T.bit_count);
+ const ByteAlignedT = @IntType(false, @divTrunc(T.bit_count + 7, 8) * 8);
+
+ var rand_bytes: [@sizeOf(ByteAlignedT)]u8 = undefined;
r.bytes(rand_bytes[0..]);
- if (T == bool) {
- return rand_bytes[0] & 0b1 == 0;
- } else {
- // NOTE: Cannot @bitCast array to integer type.
- return mem.readInt(rand_bytes, T, builtin.Endian.Little);
+ // use LE instead of native endian for better portability maybe?
+ // TODO: endian portability is pointless if the underlying prng isn't endian portable.
+ // TODO: document the endian portability of this library.
+ const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);
+ const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
+ return @bitCast(T, unsigned_result);
+ }
+
+ /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
+ /// This function assumes that the underlying ::fillFn produces evenly distributed values.
+ /// Within this assumption, the runtime of this function is exponentially distributed.
+ /// If ::fillFn were backed by a true random generator,
+ /// the runtime of this function would technically be unbounded.
+ /// However, if ::fillFn is backed by any evenly distributed pseudo random number generator,
+ /// this function is guaranteed to return.
+ /// If you need deterministic runtime bounds, consider instead using `r.int(T) % less_than`,
+ /// which will usually be biased toward smaller values.
+ pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
+ assert(T.is_signed == false);
+ assert(0 < less_than);
+
+ const last_group_size_minus_one: T = @maxValue(T) % less_than;
+ if (last_group_size_minus_one == less_than - 1) {
+ // less_than is a power of two.
+ assert(math.floorPowerOfTwo(T, less_than) == less_than);
+ // There is no retry zone. The optimal retry_zone_start would be @maxValue(T) + 1.
+ return r.int(T) % less_than;
}
+ const retry_zone_start = @maxValue(T) - last_group_size_minus_one;
+
+ while (true) {
+ const rand_val = r.int(T);
+ if (rand_val < retry_zone_start) {
+ return rand_val % less_than;
+ }
+ }
+ }
+
+ /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
+ /// See ::uintLessThan, which this function uses in most cases,
+ /// for commentary on the runtime of this function.
+ pub fn uintAtMost(r: *Random, comptime T: type, at_most: T) T {
+ assert(T.is_signed == false);
+ if (at_most == @maxValue(T)) {
+ // have the full range
+ return r.int(T);
+ }
+ return r.uintLessThan(T, at_most + 1);
+ }
+
+ /// Returns an evenly distributed random integer `at_least <= i < less_than`.
+ /// See ::uintLessThan, which this function uses in most cases,
+ /// for commentary on the runtime of this function.
+ pub fn intRangeLessThan(r: *Random, comptime T: type, at_least: T, less_than: T) T {
+ assert(at_least < less_than);
+ if (T.is_signed) {
+ // Two's complement makes this math pretty easy.
+ const UnsignedT = @IntType(false, T.bit_count);
+ const lo = @bitCast(UnsignedT, at_least);
+ const hi = @bitCast(UnsignedT, less_than);
+ const result = lo +% r.uintLessThan(UnsignedT, hi -% lo);
+ return @bitCast(T, result);
+ } else {
+ // The signed implementation would work fine, but we can use stricter arithmetic operators here.
+ return at_least + r.uintLessThan(T, less_than - at_least);
+ }
+ }
+
+ /// Returns an evenly distributed random integer `at_least <= i <= at_most`.
+ /// See ::uintLessThan, which this function uses in most cases,
+ /// for commentary on the runtime of this function.
+ pub fn intRangeAtMost(r: *Random, comptime T: type, at_least: T, at_most: T) T {
+ assert(at_least <= at_most);
+ if (T.is_signed) {
+ // Two's complement makes this math pretty easy.
+ const UnsignedT = @IntType(false, T.bit_count);
+ const lo = @bitCast(UnsignedT, at_least);
+ const hi = @bitCast(UnsignedT, at_most);
+ const result = lo +% r.uintAtMost(UnsignedT, hi -% lo);
+ return @bitCast(T, result);
+ } else {
+ // The signed implementation would work fine, but we can use stricter arithmetic operators here.
+ return at_least + r.uintAtMost(T, at_most - at_least);
+ }
+ }
+
+ /// Return a random integer/boolean type.
+ /// TODO: deprecated. use ::boolean or ::int instead.
+ pub fn scalar(r: *Random, comptime T: type) T {
+ if (T == bool) return r.boolean();
+ return r.int(T);
}
/// Return a random integer with even distribution between `start`
/// inclusive and `end` exclusive. `start` must be less than `end`.
+ /// TODO: deprecated. renamed to ::intRangeLessThan
pub fn range(r: *Random, comptime T: type, start: T, end: T) T {
- assert(start < end);
- if (T.is_signed) {
- const uint = @IntType(false, T.bit_count);
- if (start >= 0 and end >= 0) {
- return @intCast(T, r.range(uint, @intCast(uint, start), @intCast(uint, end)));
- } else if (start < 0 and end < 0) {
- // Can't overflow because the range is over signed ints
- return math.negateCast(r.range(uint, math.absCast(end), math.absCast(start)) + 1) catch unreachable;
- } else if (start < 0 and end >= 0) {
- const end_uint = @intCast(uint, end);
- const total_range = math.absCast(start) + end_uint;
- const value = r.range(uint, 0, total_range);
- const result = if (value < end_uint) x: {
- break :x @intCast(T, value);
- } else if (value == end_uint) x: {
- break :x start;
- } else x: {
- // Can't overflow because the range is over signed ints
- break :x math.negateCast(value - end_uint) catch unreachable;
- };
- return result;
- } else {
- unreachable;
- }
- } else {
- const total_range = end - start;
- const leftover = @maxValue(T) % total_range;
- const upper_bound = @maxValue(T) - leftover;
- var rand_val_array: [@sizeOf(T)]u8 = undefined;
-
- while (true) {
- r.bytes(rand_val_array[0..]);
- const rand_val = mem.readInt(rand_val_array, T, builtin.Endian.Little);
- if (rand_val < upper_bound) {
- return start + (rand_val % total_range);
- }
- }
- }
+ return r.intRangeLessThan(T, start, end);
}
/// Return a floating point value evenly distributed in the range [0, 1).
@@ -97,12 +154,12 @@ pub const Random = struct {
// Note: The lowest mantissa bit is always set to 0 so we only use half the available range.
switch (T) {
f32 => {
- const s = r.scalar(u32);
+ const s = r.int(u32);
const repr = (0x7f << 23) | (s >> 9);
return @bitCast(f32, repr) - 1.0;
},
f64 => {
- const s = r.scalar(u64);
+ const s = r.int(u64);
const repr = (0x3ff << 52) | (s >> 12);
return @bitCast(f64, repr) - 1.0;
},
@@ -142,12 +199,167 @@ pub const Random = struct {
var i: usize = 0;
while (i < buf.len - 1) : (i += 1) {
- const j = r.range(usize, i, buf.len);
+ const j = r.intRangeLessThan(usize, i, buf.len);
mem.swap(T, &buf[i], &buf[j]);
}
}
};
+const SequentialPrng = struct {
+ const Self = @This();
+ random: Random,
+ next_value: u8,
+
+ pub fn init() Self {
+ return Self{
+ .random = Random{ .fillFn = fill },
+ .next_value = 0,
+ };
+ }
+
+ fn fill(r: *Random, buf: []u8) void {
+ const self = @fieldParentPtr(Self, "random", r);
+ for (buf) |*b| {
+ b.* = self.next_value;
+ }
+ self.next_value +%= 1;
+ }
+};
+
+test "Random int" {
+ testRandomInt();
+ comptime testRandomInt();
+}
+fn testRandomInt() void {
+ var r = SequentialPrng.init();
+
+ assert(r.random.int(u0) == 0);
+
+ r.next_value = 0;
+ assert(r.random.int(u1) == 0);
+ assert(r.random.int(u1) == 1);
+ assert(r.random.int(u2) == 2);
+ assert(r.random.int(u2) == 3);
+ assert(r.random.int(u2) == 0);
+
+ r.next_value = 0xff;
+ assert(r.random.int(u8) == 0xff);
+ r.next_value = 0x11;
+ assert(r.random.int(u8) == 0x11);
+
+ r.next_value = 0xff;
+ assert(r.random.int(u32) == 0xffffffff);
+ r.next_value = 0x11;
+ assert(r.random.int(u32) == 0x11111111);
+
+ r.next_value = 0xff;
+ assert(r.random.int(i32) == -1);
+ r.next_value = 0x11;
+ assert(r.random.int(i32) == 0x11111111);
+
+ r.next_value = 0xff;
+ assert(r.random.int(i8) == -1);
+ r.next_value = 0x11;
+ assert(r.random.int(i8) == 0x11);
+
+ r.next_value = 0xff;
+ assert(r.random.int(u33) == 0x1ffffffff);
+ r.next_value = 0xff;
+ assert(r.random.int(i1) == -1);
+ r.next_value = 0xff;
+ assert(r.random.int(i2) == -1);
+ r.next_value = 0xff;
+ assert(r.random.int(i33) == -1);
+}
+
+test "Random boolean" {
+ testRandomBoolean();
+ comptime testRandomBoolean();
+}
+fn testRandomBoolean() void {
+ var r = SequentialPrng.init();
+ assert(r.random.boolean() == false);
+ assert(r.random.boolean() == true);
+ assert(r.random.boolean() == false);
+ assert(r.random.boolean() == true);
+}
+
+test "Random intLessThan" {
+ @setEvalBranchQuota(10000);
+ testRandomIntLessThan();
+ comptime testRandomIntLessThan();
+}
+fn testRandomIntLessThan() void {
+ var r = SequentialPrng.init();
+ r.next_value = 0xff;
+ assert(r.random.uintLessThan(u8, 4) == 3);
+ r.next_value = 0xff;
+ assert(r.random.uintLessThan(u8, 3) == 0);
+ assert(r.next_value == 1);
+
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);
+
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
+
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(i64, -0x8000000000000000, 0) == -1);
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
+ r.next_value = 0xff;
+ assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
+
+ // test retrying and eventually getting a good value
+ // start just out of bounds
+ r.next_value = 0x81;
+ assert(r.random.uintLessThan(u8, 0x81) == 0);
+}
+
+test "Random intAtMost" {
+ @setEvalBranchQuota(10000);
+ testRandomIntAtMost();
+ comptime testRandomIntAtMost();
+}
+fn testRandomIntAtMost() void {
+ var r = SequentialPrng.init();
+ r.next_value = 0xff;
+ assert(r.random.uintAtMost(u8, 3) == 3);
+ r.next_value = 0xff;
+ assert(r.random.uintAtMost(u8, 2) == 0);
+ assert(r.next_value == 1);
+
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);
+
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
+
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(i64, -0x8000000000000000, -1) == -1);
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
+ r.next_value = 0xff;
+ assert(r.random.intRangeAtMost(i3, -2, 1) == 1);
+
+ // test retrying and eventually getting a good value
+ // start just out of bounds
+ r.next_value = 0x81;
+ assert(r.random.uintAtMost(u8, 0x80) == 0);
+}
+
// Generator to extend 64-bit seed values into longer sequences.
//
// The number of cycles is thus limited to 64-bits regardless of the engine, but this
@@ -622,17 +834,6 @@ test "Random float" {
}
}
-test "Random scalar" {
- var prng = DefaultPrng.init(0);
- const s = prng.random.scalar(u64);
-}
-
-test "Random bytes" {
- var prng = DefaultPrng.init(0);
- var buf: [2048]u8 = undefined;
- prng.random.bytes(buf[0..]);
-}
-
test "Random shuffle" {
var prng = DefaultPrng.init(0);
@@ -664,16 +865,16 @@ test "Random range" {
testRange(&prng.random, -4, 3);
testRange(&prng.random, -4, -1);
testRange(&prng.random, 10, 14);
- // TODO: test that prng.random.range(1, 1) causes an assertion error
+ testRange(&prng.random, -0x80, 0x7f);
}
-fn testRange(r: *Random, start: i32, end: i32) void {
- const count = @intCast(usize, end - start);
- var values_buffer = []bool{false} ** 20;
+fn testRange(r: *Random, start: i8, end: i8) void {
+ const count = @intCast(usize, i32(end) - i32(start));
+ var values_buffer = []bool{false} ** 0x100;
const values = values_buffer[0..count];
var i: usize = 0;
while (i < count) {
- const value = r.range(i32, start, end);
+ const value: i32 = r.intRangeLessThan(i8, start, end);
const index = @intCast(usize, value - start);
if (!values[index]) {
i += 1;
From af3263d7a87c922cbcb047944ee94123c69cfac1 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 27 Sep 2018 10:22:16 -0400
Subject: [PATCH 046/127] add dll export storage class where appropriate
closes #1443
---
src/codegen.cpp | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 176b7bb08b..70310641c4 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -446,6 +446,21 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
return first_arg_ret ? 1 : 0;
}
+static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
+ if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
+ LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
+ }
+}
+
+static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
+ if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
+ // TODO come up with a good explanation/understanding for why we never do
+ // DLLImportStorageClass. Empirically it only causes problems. But let's have
+ // this documented and then clean up the code accordingly.
+ //LLVMSetDLLStorageClass(global_value, LLVMDLLImportStorageClass);
+ }
+}
+
static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
if (fn_table_entry->llvm_value)
return fn_table_entry->llvm_value;
@@ -539,6 +554,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
}
if (fn_table_entry->body_node != nullptr) {
+ maybe_export_dll(g, fn_table_entry->llvm_value, linkage);
+
bool want_fn_safety = g->build_mode != BuildModeFastRelease &&
g->build_mode != BuildModeSmallRelease &&
!fn_table_entry->def_scope->safety_off;
@@ -548,6 +565,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
}
}
+ } else {
+ maybe_import_dll(g, fn_table_entry->llvm_value, linkage);
}
if (fn_table_entry->alignstack_value != 0) {
@@ -6107,6 +6126,7 @@ static void do_code_gen(CodeGen *g) {
// TODO debug info for the extern variable
LLVMSetLinkage(global_value, LLVMExternalLinkage);
+ maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
LLVMSetAlignment(global_value, var->align_bytes);
LLVMSetGlobalConstant(global_value, var->gen_is_const);
}
@@ -6119,6 +6139,7 @@ static void do_code_gen(CodeGen *g) {
if (exported) {
LLVMSetLinkage(global_value, LLVMExternalLinkage);
+ maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
}
if (tld_var->section_name) {
LLVMSetSection(global_value, buf_ptr(tld_var->section_name));
From cc490f00267cb593412be05eba521c538943efef Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 27 Sep 2018 12:34:41 -0400
Subject: [PATCH 047/127] update @typeInfo docs
---
doc/langref.html.in | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index bc7bbf0cbb..3485fda815 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -6295,7 +6295,6 @@ pub const TypeInfo = union(TypeId) {
Union: Union,
Fn: Fn,
Namespace: void,
- Block: void,
BoundFn: Fn,
ArgTuple: void,
Opaque: void,
@@ -6315,7 +6314,7 @@ pub const TypeInfo = union(TypeId) {
size: Size,
is_const: bool,
is_volatile: bool,
- alignment: u29,
+ alignment: u32,
child: type,
pub const Size = enum {
From fe524a1fa565004c3c0c3faecbe14f2331feefab Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 27 Sep 2018 15:07:51 -0400
Subject: [PATCH 048/127] build: add support for ZIG_STATIC on MacOS
---
CMakeLists.txt | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64288a5ce9..e6d02a4fb5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,6 +67,14 @@ if(NOT MSVC)
else()
message("${ZLIB} found")
endif()
+
+ if(APPLE AND ZIG_STATIC)
+ list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
+ list(REMOVE_ITEM LLVM_LIBRARIES "-lxml2")
+ list(REMOVE_ITEM LLVM_LIBRARIES "-lcurses")
+ find_library(LIBNCURSES NAMES libncurses.a)
+ list(APPEND LLVM_LIBRARIES "${LIBNCURSES}" "${LIBXML2}" "${ZLIB}")
+ endif()
endif()
set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")
@@ -815,7 +823,11 @@ if(MINGW)
elseif(MSVC)
set(EXE_LDFLAGS "/STACK:16777216")
elseif(ZIG_STATIC)
- set(EXE_LDFLAGS "-static")
+ if(APPLE)
+ set(EXE_LDFLAGS " ")
+ else()
+ set(EXE_LDFLAGS "-static")
+ endif()
else()
set(EXE_LDFLAGS " ")
endif()
From f4a0658585574d904190732fbacedccb1e8b6f46 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 27 Sep 2018 22:27:52 -0400
Subject: [PATCH 049/127] rely on gcc for static builds on macos
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e6d02a4fb5..70ca29b2e9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -824,7 +824,7 @@ elseif(MSVC)
set(EXE_LDFLAGS "/STACK:16777216")
elseif(ZIG_STATIC)
if(APPLE)
- set(EXE_LDFLAGS " ")
+ set(EXE_LDFLAGS "-static-libgcc -static-libstdc++")
else()
set(EXE_LDFLAGS "-static")
endif()
From e242f6a609eb4d8367e2bf22ce82e210df3142bb Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 28 Sep 2018 09:03:40 -0400
Subject: [PATCH 050/127] Release 0.3.0
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 70ca29b2e9..22f365aafe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(ZIG_VERSION_MAJOR 0)
-set(ZIG_VERSION_MINOR 2)
+set(ZIG_VERSION_MINOR 3)
set(ZIG_VERSION_PATCH 0)
set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")
From 779881b978e1275eef2e3b247ec0909260f4219e Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 28 Sep 2018 16:41:23 -0400
Subject: [PATCH 051/127] zig build: use os_self_exe_path to determine exe path
not arg0
---
src/main.cpp | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/main.cpp b/src/main.cpp
index cdb68ec529..5c1e107362 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -394,7 +394,12 @@ int main(int argc, char **argv) {
bool no_rosegment_workaround = false;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
- const char *zig_exe_path = arg0;
+ Buf zig_exe_path_buf = BUF_INIT;
+ if ((err = os_self_exe_path(&zig_exe_path_buf))) {
+ fprintf(stderr, "Unable to determine path to zig's own executable\n");
+ return EXIT_FAILURE;
+ }
+ const char *zig_exe_path = buf_ptr(&zig_exe_path_buf);
const char *build_file = "build.zig";
bool asked_for_help = false;
From 1428ef3b07eba5a414b30973b117f3c8328c727c Mon Sep 17 00:00:00 2001
From: Jimmi Holst Christensen
Date: Sun, 30 Sep 2018 01:23:05 +0200
Subject: [PATCH 052/127] Expose failing_allocator as *Allocator instead of
const FailingAllocator
---
std/debug/index.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/std/debug/index.zig b/std/debug/index.zig
index 9ad15ccd7e..4a8ee365ba 100644
--- a/std/debug/index.zig
+++ b/std/debug/index.zig
@@ -13,7 +13,7 @@ const ArrayList = std.ArrayList;
const builtin = @import("builtin");
pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
-pub const failing_allocator = FailingAllocator.init(global_allocator, 0);
+pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;
pub const runtime_safety = switch (builtin.mode) {
builtin.Mode.Debug, builtin.Mode.ReleaseSafe => true,
From d3bf2671362b1b4550369316b7259d55d98c80cc Mon Sep 17 00:00:00 2001
From: emekoi
Date: Thu, 27 Sep 2018 00:18:47 -0500
Subject: [PATCH 053/127] added dynamic library loading for windows
---
std/dynamic_library.zig | 39 ++++++++++++++++++++++++++++++++++---
std/os/windows/index.zig | 1 +
std/os/windows/kernel32.zig | 34 +++++++++++++++++---------------
3 files changed, 55 insertions(+), 19 deletions(-)
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index ed190f7deb..10068e83a8 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -1,10 +1,19 @@
-const std = @import("index.zig");
+const builtin = @import("builtin");
+const Os = builtin.Os;
+const std = @import("std");
const mem = std.mem;
const elf = std.elf;
const cstr = std.cstr;
const linux = std.os.linux;
+const windows = std.os.windows;
-pub const DynLib = struct {
+pub const DynLib = switch (builtin.os) {
+ Os.linux => LinuxDynLib,
+ Os.windows => WindowsDynLib,
+ else => void,
+};
+
+pub const LinuxDynLib = struct {
allocator: *mem.Allocator,
elf_lib: ElfLib,
fd: i32,
@@ -107,7 +116,7 @@ pub const ElfLib = struct {
}
}
- return ElfLib{
+ return ElfLib {
.base = base,
.strings = maybe_strings orelse return error.ElfStringSectionNotFound,
.syms = maybe_syms orelse return error.ElfSymSectionNotFound,
@@ -154,3 +163,27 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));
}
+
+pub const WindowsDynLib = struct {
+ allocator: *mem.Allocator,
+ dll: windows.HMODULE,
+
+ pub fn open(allocator: *mem.Allocator, path: []const u8) !WindowsDynLib {
+ const wpath = try std.unicode.utf8ToUtf16LeWithNull(allocator, path);
+ defer allocator.free(wpath);
+
+ return WindowsDynLib {
+ .allocator = allocator,
+ .dll = windows.LoadLibraryW(wpath[0..].ptr) orelse return error.FileNotFound
+ };
+ }
+
+ pub fn close(self: *WindowsDynLib) void {
+ _ = windows.FreeLibrary(self.dll);
+ self.* = undefined;
+ }
+
+ pub fn lookup(self: *WindowsDynLib, name: []const u8) ?usize {
+ return @ptrToInt(windows.GetProcAddress(self.dll, name.ptr));
+ }
+};
diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig
index fc64db7c37..9d03cf6625 100644
--- a/std/os/windows/index.zig
+++ b/std/os/windows/index.zig
@@ -24,6 +24,7 @@ pub const HANDLE = *c_void;
pub const HCRYPTPROV = ULONG_PTR;
pub const HINSTANCE = *@OpaqueType();
pub const HMODULE = *@OpaqueType();
+pub const FARPROC = *@OpaqueType();
pub const INT = c_int;
pub const LPBYTE = *BYTE;
pub const LPCH = *CHAR;
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index 94b339fa6e..9fbd22b66a 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -4,10 +4,10 @@ pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVE
pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
-pub extern "kernel32" stdcallcc fn CreateDirectoryW(lpPathName: [*]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) BOOL;
+pub extern "kernel32" stdcallcc fn CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) BOOL;
pub extern "kernel32" stdcallcc fn CreateFileW(
- lpFileName: [*]const u16, // TODO null terminated pointer type
+ lpFileName: LPCWSTR, // TODO null terminated pointer type
dwDesiredAccess: DWORD,
dwShareMode: DWORD,
lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES,
@@ -36,21 +36,21 @@ pub extern "kernel32" stdcallcc fn CreateProcessW(
lpProcessInformation: *PROCESS_INFORMATION,
) BOOL;
-pub extern "kernel32" stdcallcc fn CreateSymbolicLinkW(lpSymlinkFileName: [*]const u16, lpTargetFileName: [*]const u16, dwFlags: DWORD) BOOLEAN;
+pub extern "kernel32" stdcallcc fn CreateSymbolicLinkW(lpSymlinkFileName: LPCWSTR, lpTargetFileName: LPCWSTR, dwFlags: DWORD) BOOLEAN;
pub extern "kernel32" stdcallcc fn CreateIoCompletionPort(FileHandle: HANDLE, ExistingCompletionPort: ?HANDLE, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD) ?HANDLE;
pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: ?LPVOID, dwCreationFlags: DWORD, lpThreadId: ?LPDWORD) ?HANDLE;
-pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;
+pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: LPCWSTR) BOOL;
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
-pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
+pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
-pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;
+pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPSTR) BOOL;
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
@@ -63,7 +63,7 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
-pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
+pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?LPSTR;
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;
@@ -73,7 +73,7 @@ pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: *LAR
pub extern "kernel32" stdcallcc fn GetFileAttributesW(lpFileName: [*]const WCHAR) DWORD;
-pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) DWORD;
+pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: LPWSTR, nSize: DWORD) DWORD;
pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) HMODULE;
@@ -88,7 +88,7 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(
pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleW(
hFile: HANDLE,
- lpszFilePath: [*]u16,
+ lpszFilePath: LPWSTR,
cchFilePath: DWORD,
dwFlags: DWORD,
) DWORD;
@@ -117,8 +117,8 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL;
pub extern "kernel32" stdcallcc fn MoveFileExW(
- lpExistingFileName: [*]const u16,
- lpNewFileName: [*]const u16,
+ lpExistingFileName: LPCWSTR,
+ lpNewFileName: LPCWSTR,
dwFlags: DWORD,
) BOOL;
@@ -141,13 +141,13 @@ pub extern "kernel32" stdcallcc fn ReadDirectoryChangesW(
pub extern "kernel32" stdcallcc fn ReadFile(
in_hFile: HANDLE,
- out_lpBuffer: [*]u8,
+ out_lpBuffer: LPSTR,
in_nNumberOfBytesToRead: DWORD,
out_lpNumberOfBytesRead: ?*DWORD,
in_out_lpOverlapped: ?*OVERLAPPED,
) BOOL;
-pub extern "kernel32" stdcallcc fn RemoveDirectoryW(lpPathName: [*]const u16) BOOL;
+pub extern "kernel32" stdcallcc fn RemoveDirectoryW(lpPathName: LPCWSTR) BOOL;
pub extern "kernel32" stdcallcc fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) BOOL;
@@ -168,15 +168,17 @@ pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMillis
pub extern "kernel32" stdcallcc fn WriteFile(
in_hFile: HANDLE,
- in_lpBuffer: [*]const u8,
+ in_lpBuffer: LPCSTR,
in_nNumberOfBytesToWrite: DWORD,
out_lpNumberOfBytesWritten: ?*DWORD,
in_out_lpOverlapped: ?*OVERLAPPED,
) BOOL;
-pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const u8, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;
+pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: LPCSTR, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;
-pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
+pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: LPCWSTR) ?HMODULE;
+
+pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) ?FARPROC;
pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL;
From 42ba206c5d0701989f15d554d89c7d84667a7086 Mon Sep 17 00:00:00 2001
From: emekoi
Date: Thu, 27 Sep 2018 00:47:54 -0500
Subject: [PATCH 054/127] fixed compilation on mingw
---
CMakeLists.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22f365aafe..bba4dd6881 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -211,6 +211,9 @@ else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
+ if(MINGW)
+ set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
+ endif()
endif()
set_target_properties(embedded_lld_lib PROPERTIES
COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
From 623f5085f152b3a2fedf3b4e4451910f1edb6739 Mon Sep 17 00:00:00 2001
From: emekoi
Date: Thu, 27 Sep 2018 16:51:22 -0500
Subject: [PATCH 055/127] merged windows dll apis
---
std/dynamic_library.zig | 41 +++++++++++++++++++++++++++++--------
std/os/index.zig | 2 --
std/os/windows/kernel32.zig | 34 +++++++++++++++---------------
std/os/windows/util.zig | 31 ----------------------------
4 files changed, 50 insertions(+), 58 deletions(-)
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 10068e83a8..c0922003ce 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -1,11 +1,15 @@
const builtin = @import("builtin");
const Os = builtin.Os;
-const std = @import("std");
+
+const std = @import("index.zig");
const mem = std.mem;
-const elf = std.elf;
const cstr = std.cstr;
-const linux = std.os.linux;
-const windows = std.os.windows;
+const os = std.os;
+const assert = std.debug.assert;
+const elf = std.elf;
+const linux = os.linux;
+const windows = os.windows;
+const win_util = @import("os/windows/util.zig");
pub const DynLib = switch (builtin.os) {
Os.linux => LinuxDynLib,
@@ -169,17 +173,24 @@ pub const WindowsDynLib = struct {
dll: windows.HMODULE,
pub fn open(allocator: *mem.Allocator, path: []const u8) !WindowsDynLib {
- const wpath = try std.unicode.utf8ToUtf16LeWithNull(allocator, path);
- defer allocator.free(wpath);
+ const wpath = try win_util.sliceToPrefixedFileW(path);
return WindowsDynLib {
.allocator = allocator,
- .dll = windows.LoadLibraryW(wpath[0..].ptr) orelse return error.FileNotFound
+ .dll = windows.LoadLibraryW(&wpath) orelse {
+ const err = windows.GetLastError();
+ switch (err) {
+ windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
+ windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
+ windows.ERROR.MOD_NOT_FOUND => return error.FileNotFound,
+ else => return os.unexpectedErrorWindows(err),
+ }
+ },
};
}
pub fn close(self: *WindowsDynLib) void {
- _ = windows.FreeLibrary(self.dll);
+ assert(windows.FreeLibrary(self.dll) != 0);
self.* = undefined;
}
@@ -187,3 +198,17 @@ pub const WindowsDynLib = struct {
return @ptrToInt(windows.GetProcAddress(self.dll, name.ptr));
}
};
+
+test "dynamic_library" {
+ const libname = switch (builtin.os) {
+ Os.linux => "invalid_so.so",
+ Os.windows => "invalid_dll.dll",
+ else => return;,
+ };
+
+ const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
+ assert(err == error.FileNotFound);
+ return;
+ };
+ @panic("Expected error from function");
+}
diff --git a/std/os/index.zig b/std/os/index.zig
index 1ce9bd7278..a53d1d2050 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -58,8 +58,6 @@ pub const windowsWrite = windows_util.windowsWrite;
pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
pub const windowsOpen = windows_util.windowsOpen;
pub const windowsOpenW = windows_util.windowsOpenW;
-pub const windowsLoadDll = windows_util.windowsLoadDll;
-pub const windowsUnloadDll = windows_util.windowsUnloadDll;
pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock;
pub const WindowsCreateIoCompletionPortError = windows_util.WindowsCreateIoCompletionPortError;
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index 9fbd22b66a..7eec5faba9 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -4,10 +4,10 @@ pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVE
pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
-pub extern "kernel32" stdcallcc fn CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) BOOL;
+pub extern "kernel32" stdcallcc fn CreateDirectoryW(lpPathName: [*]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) BOOL;
pub extern "kernel32" stdcallcc fn CreateFileW(
- lpFileName: LPCWSTR, // TODO null terminated pointer type
+ lpFileName: [*]const u16, // TODO null terminated pointer type
dwDesiredAccess: DWORD,
dwShareMode: DWORD,
lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES,
@@ -36,21 +36,21 @@ pub extern "kernel32" stdcallcc fn CreateProcessW(
lpProcessInformation: *PROCESS_INFORMATION,
) BOOL;
-pub extern "kernel32" stdcallcc fn CreateSymbolicLinkW(lpSymlinkFileName: LPCWSTR, lpTargetFileName: LPCWSTR, dwFlags: DWORD) BOOLEAN;
+pub extern "kernel32" stdcallcc fn CreateSymbolicLinkW(lpSymlinkFileName: [*]const u16, lpTargetFileName: [*]const u16, dwFlags: DWORD) BOOLEAN;
pub extern "kernel32" stdcallcc fn CreateIoCompletionPort(FileHandle: HANDLE, ExistingCompletionPort: ?HANDLE, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD) ?HANDLE;
pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: ?LPVOID, dwCreationFlags: DWORD, lpThreadId: ?LPDWORD) ?HANDLE;
-pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: LPCWSTR) BOOL;
+pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
-pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
+pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
-pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPSTR) BOOL;
+pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
@@ -63,7 +63,7 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
-pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?LPSTR;
+pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;
@@ -73,7 +73,7 @@ pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: *LAR
pub extern "kernel32" stdcallcc fn GetFileAttributesW(lpFileName: [*]const WCHAR) DWORD;
-pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: LPWSTR, nSize: DWORD) DWORD;
+pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) DWORD;
pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) HMODULE;
@@ -88,7 +88,7 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(
pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleW(
hFile: HANDLE,
- lpszFilePath: LPWSTR,
+ lpszFilePath: [*]u16,
cchFilePath: DWORD,
dwFlags: DWORD,
) DWORD;
@@ -117,8 +117,8 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem
pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL;
pub extern "kernel32" stdcallcc fn MoveFileExW(
- lpExistingFileName: LPCWSTR,
- lpNewFileName: LPCWSTR,
+ lpExistingFileName: [*]const u16,
+ lpNewFileName: [*]const u16,
dwFlags: DWORD,
) BOOL;
@@ -141,13 +141,13 @@ pub extern "kernel32" stdcallcc fn ReadDirectoryChangesW(
pub extern "kernel32" stdcallcc fn ReadFile(
in_hFile: HANDLE,
- out_lpBuffer: LPSTR,
+ out_lpBuffer: [*]u8,
in_nNumberOfBytesToRead: DWORD,
out_lpNumberOfBytesRead: ?*DWORD,
in_out_lpOverlapped: ?*OVERLAPPED,
) BOOL;
-pub extern "kernel32" stdcallcc fn RemoveDirectoryW(lpPathName: LPCWSTR) BOOL;
+pub extern "kernel32" stdcallcc fn RemoveDirectoryW(lpPathName: [*]const u16) BOOL;
pub extern "kernel32" stdcallcc fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) BOOL;
@@ -168,17 +168,17 @@ pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMillis
pub extern "kernel32" stdcallcc fn WriteFile(
in_hFile: HANDLE,
- in_lpBuffer: LPCSTR,
+ in_lpBuffer: [*]const u8,
in_nNumberOfBytesToWrite: DWORD,
out_lpNumberOfBytesWritten: ?*DWORD,
in_out_lpOverlapped: ?*OVERLAPPED,
) BOOL;
-pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: LPCSTR, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;
+pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const u8, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;
-pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: LPCWSTR) ?HMODULE;
+pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
-pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) ?FARPROC;
+pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;
pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL;
diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig
index 6534d16f5e..7d983421e0 100644
--- a/std/os/windows/util.zig
+++ b/std/os/windows/util.zig
@@ -188,37 +188,6 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
return allocator.shrink(u16, result, i);
}
-pub fn windowsLoadDllW(dll_path_w: [*]const u16) !windows.HMODULE {
- return windows.LoadLibraryW(dll_path_w) orelse {
- const err = windows.GetLastError();
- switch (err) {
- windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
- windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
- windows.ERROR.MOD_NOT_FOUND => return error.FileNotFound,
- else => return os.unexpectedErrorWindows(err),
- }
- };
-}
-
-pub fn windowsLoadDll(dll_path: []const u8) !windows.HMODULE {
- const dll_path_w = try sliceToPrefixedFileW(dll_path);
- return windowsLoadDllW(&dll_path_w);
-}
-
-pub fn windowsUnloadDll(hModule: windows.HMODULE) void {
- assert(windows.FreeLibrary(hModule) != 0);
-}
-
-test "InvalidDll" {
- if (builtin.os != builtin.Os.windows) return error.SkipZigTest;
-
- const handle = os.windowsLoadDll("asdf.dll") catch |err| {
- assert(err == error.FileNotFound);
- return;
- };
- @panic("Expected error from function");
-}
-
pub fn windowsFindFirstFile(
dir_path: []const u8,
find_file_data: *windows.WIN32_FIND_DATAW,
From e6446dfc86e42ccea93760d99cf4b421265cfb0e Mon Sep 17 00:00:00 2001
From: emekoi
Date: Sun, 30 Sep 2018 01:34:38 -0500
Subject: [PATCH 056/127] fixed native target detection
---
CMakeLists.txt | 3 +++
src/zig_llvm.cpp | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22f365aafe..bba4dd6881 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -211,6 +211,9 @@ else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
+ if(MINGW)
+ set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
+ endif()
endif()
set_target_properties(embedded_lld_lib PROPERTIES
COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index 8e9fe65d47..ea270bcb5a 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -712,7 +712,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
ZigLLVM_ObjectFormatType *oformat)
{
char *native_triple = LLVMGetDefaultTargetTriple();
- Triple triple(native_triple);
+ Triple triple(Triple::normalize(native_triple));
*arch_type = (ZigLLVM_ArchType)triple.getArch();
*sub_arch_type = (ZigLLVM_SubArchType)triple.getSubArch();
From 57c4d38c556238530af9b643b4dbc481de417782 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 30 Sep 2018 10:37:58 -0400
Subject: [PATCH 057/127] rename std.event.tcp to std.event.net
---
CMakeLists.txt | 2 +-
std/event.zig | 4 ++--
std/event/{tcp.zig => net.zig} | 0
3 files changed, 3 insertions(+), 3 deletions(-)
rename std/event/{tcp.zig => net.zig} (100%)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bba4dd6881..e99f2ea343 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -492,9 +492,9 @@ set(ZIG_STD_FILES
"event/lock.zig"
"event/locked.zig"
"event/loop.zig"
+ "event/net.zig"
"event/rwlock.zig"
"event/rwlocked.zig"
- "event/tcp.zig"
"fmt/errol/enum3.zig"
"fmt/errol/index.zig"
"fmt/errol/lookup.zig"
diff --git a/std/event.zig b/std/event.zig
index bd3262a575..56c5223ba3 100644
--- a/std/event.zig
+++ b/std/event.zig
@@ -7,7 +7,7 @@ pub const RwLock = @import("event/rwlock.zig").RwLock;
pub const RwLocked = @import("event/rwlocked.zig").RwLocked;
pub const Loop = @import("event/loop.zig").Loop;
pub const fs = @import("event/fs.zig");
-pub const tcp = @import("event/tcp.zig");
+pub const net = @import("event/net.zig");
test "import event tests" {
_ = @import("event/channel.zig");
@@ -19,5 +19,5 @@ test "import event tests" {
_ = @import("event/rwlock.zig");
_ = @import("event/rwlocked.zig");
_ = @import("event/loop.zig");
- _ = @import("event/tcp.zig");
+ _ = @import("event/net.zig");
}
diff --git a/std/event/tcp.zig b/std/event/net.zig
similarity index 100%
rename from std/event/tcp.zig
rename to std/event/net.zig
From 418b2e7d47cbfdd8d04c362b758c96b533674282 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 30 Sep 2018 16:45:33 -0400
Subject: [PATCH 058/127] build: omit finding libxml2, zlib since no direct
dependency
---
CMakeLists.txt | 29 +++++------------------------
README.md | 1 -
2 files changed, 5 insertions(+), 25 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e99f2ea343..98b2ab9db0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,31 +50,12 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead
find_package(llvm)
find_package(clang)
-# TODO fix https://github.com/ziglang/docker-zig/issues/7
-list(REMOVE_ITEM LLVM_LIBRARIES "-l/deps/local/lib/libxml2.a")
-
-if(NOT MSVC)
- find_library(LIBXML2 NAMES xml2 libxml2)
- if(${LIBXML2} STREQUAL "LIBXML2-NOTFOUND")
- message(FATAL_ERROR "Could not find libxml2")
- else()
- message("${LIBXML2} found")
- endif()
-
+if(APPLE AND ZIG_STATIC)
+ list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
+ list(REMOVE_ITEM LLVM_LIBRARIES "-lcurses")
find_library(ZLIB NAMES z zlib libz)
- if(${ZLIB} STREQUAL "ZLIB-NOTFOUND")
- message(FATAL_ERROR "Could not find zlib")
- else()
- message("${ZLIB} found")
- endif()
-
- if(APPLE AND ZIG_STATIC)
- list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
- list(REMOVE_ITEM LLVM_LIBRARIES "-lxml2")
- list(REMOVE_ITEM LLVM_LIBRARIES "-lcurses")
- find_library(LIBNCURSES NAMES libncurses.a)
- list(APPEND LLVM_LIBRARIES "${LIBNCURSES}" "${LIBXML2}" "${ZLIB}")
- endif()
+ find_library(LIBNCURSES NAMES libncurses.a)
+ list(APPEND LLVM_LIBRARIES "${LIBNCURSES}" "${ZLIB}")
endif()
set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")
diff --git a/README.md b/README.md
index d3a64abba3..69c52e200c 100644
--- a/README.md
+++ b/README.md
@@ -88,7 +88,6 @@ that counts as "freestanding" for the purposes of this table.
* cmake >= 2.8.5
* gcc >= 5.0.0 or clang >= 3.6.0
* LLVM, Clang, LLD development libraries == 7.x, compiled with the same gcc or clang version above
- - These depend on zlib and libxml2.
##### Windows
From ba78ae0ae73ac38a2bb32c618cd145b4d2f9602e Mon Sep 17 00:00:00 2001
From: Sahnvour
Date: Sun, 30 Sep 2018 22:59:45 +0200
Subject: [PATCH 059/127] Fixes --emit asm on windows and makes C header file
generation explicit. (#1612)
* build: only do codegen_link when emitting an actual binary. Fixes #1371
* build: only output C header file when explicitely asked to
---
src/all_types.hpp | 1 -
src/codegen.cpp | 16 ++--------------
src/link.cpp | 2 +-
src/main.cpp | 4 ++--
4 files changed, 5 insertions(+), 18 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 89c117ce82..30d941354a 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1713,7 +1713,6 @@ struct CodeGen {
uint32_t target_environ_index;
uint32_t target_oformat_index;
bool is_big_endian;
- bool want_h_file;
bool have_pub_main;
bool have_c_main;
bool have_winmain;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 70310641c4..de69b53388 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -118,7 +118,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
g->string_literals_table.init(16);
g->type_info_cache.init(32);
g->is_test_build = false;
- g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
buf_resize(&g->global_asm, 0);
for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
@@ -8127,17 +8126,6 @@ static void resolve_out_paths(CodeGen *g) {
} else {
zig_unreachable();
}
-
- if (g->want_h_file && !g->out_h_path) {
- assert(g->root_out_name);
- Buf *h_basename = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
- if (g->enable_cache) {
- g->out_h_path = buf_alloc();
- os_path_join(&g->artifact_dir, h_basename, g->out_h_path);
- } else {
- g->out_h_path = h_basename;
- }
- }
}
@@ -8193,11 +8181,11 @@ void codegen_build_and_link(CodeGen *g) {
codegen_add_time_event(g, "LLVM Emit Output");
zig_llvm_emit_output(g);
- if (g->want_h_file) {
+ if (g->out_h_path != nullptr) {
codegen_add_time_event(g, "Generate .h");
gen_h_file(g);
}
- if (g->out_type != OutTypeObj) {
+ if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
codegen_link(g);
}
}
diff --git a/src/link.cpp b/src/link.cpp
index aa0edde61b..a280c31f74 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -34,7 +34,7 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode,
parent_gen->zig_lib_dir);
- child_gen->want_h_file = false;
+ child_gen->out_h_path = nullptr;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
child_gen->verbose_ast = parent_gen->verbose_ast;
child_gen->verbose_link = parent_gen->verbose_link;
diff --git a/src/main.cpp b/src/main.cpp
index 5c1e107362..f9df802cb3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -52,7 +52,7 @@ static int print_full_usage(const char *arg0) {
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
" --name [name] override output name\n"
" --output [file] override destination path\n"
- " --output-h [file] override generated header file path\n"
+ " --output-h [file] generate header file\n"
" --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
" --pkg-end pop current pkg\n"
" --release-fast build with optimizations on and safety off\n"
@@ -926,7 +926,7 @@ int main(int argc, char **argv) {
if (out_file)
codegen_set_output_path(g, buf_create_from_str(out_file));
- if (out_file_h)
+ if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib))
codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
From 9d4eaf1e07525a72fa54cfaa346a18bf18953af4 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 30 Sep 2018 17:23:42 -0400
Subject: [PATCH 060/127] update std lib API for I/O
std.io.FileInStream -> std.os.File.InStream
std.io.FileInStream.init(file) -> file.inStream()
std.io.FileOutStream -> std.os.File.OutStream
std.io.FileOutStream.init(file) -> file.outStream()
remove a lot of error code possibilities from os functions
std.event.net.socketRead -> std.event.net.read
std.event.net.socketWrite -> std.event.net.write
add std.event.net.readv
add std.event.net.writev
add std.event.net.readvPosix
add std.event.net.writevPosix
add std.event.net.OutStream
add std.event.net.InStream
add std.event.io.InStream
add std.event.io.OutStream
---
CMakeLists.txt | 1 +
doc/docgen.zig | 6 +-
example/guess_number/main.zig | 3 +-
src-self-hosted/errmsg.zig | 2 +-
src-self-hosted/libc_installation.zig | 4 +-
src-self-hosted/main.zig | 10 +-
std/atomic/queue.zig | 2 +-
std/coff.zig | 8 +-
std/crypto/throughput_test.zig | 2 +-
std/debug/index.zig | 22 +-
std/elf.zig | 4 +-
std/event.zig | 2 +
std/event/fs.zig | 2 -
std/event/io.zig | 48 ++++
std/event/net.zig | 268 +++++++++++++++++------
std/io.zig | 58 +----
std/io_test.zig | 8 +-
std/os/child_process.zig | 4 +-
std/os/file.zig | 46 +++-
std/os/index.zig | 132 +++++------
std/os/linux/index.zig | 8 +
std/pdb.zig | 6 +-
std/special/build_runner.zig | 8 +-
std/zig/bench.zig | 2 +-
std/zig/parser_test.zig | 2 +-
test/compare_output.zig | 30 +--
test/standalone/brace_expansion/main.zig | 2 +-
test/tests.zig | 12 +-
28 files changed, 441 insertions(+), 261 deletions(-)
create mode 100644 std/event/io.zig
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 98b2ab9db0..25c0dfa126 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -470,6 +470,7 @@ set(ZIG_STD_FILES
"event/fs.zig"
"event/future.zig"
"event/group.zig"
+ "event/io.zig"
"event/lock.zig"
"event/locked.zig"
"event/loop.zig"
diff --git a/doc/docgen.zig b/doc/docgen.zig
index cbfd67c740..2e2aa4b420 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -41,12 +41,12 @@ pub fn main() !void {
var out_file = try os.File.openWrite(out_file_name);
defer out_file.close();
- var file_in_stream = io.FileInStream.init(in_file);
+ var file_in_stream = in_file.inStream();
const input_file_bytes = try file_in_stream.stream.readAllAlloc(allocator, max_doc_file_size);
- var file_out_stream = io.FileOutStream.init(out_file);
- var buffered_out_stream = io.BufferedOutStream(io.FileOutStream.Error).init(&file_out_stream.stream);
+ var file_out_stream = out_file.outStream();
+ var buffered_out_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
var tokenizer = Tokenizer.init(in_file_name, input_file_bytes);
var toc = try genToc(allocator, &tokenizer);
diff --git a/example/guess_number/main.zig b/example/guess_number/main.zig
index 062f93e7f7..ef0b9c08f3 100644
--- a/example/guess_number/main.zig
+++ b/example/guess_number/main.zig
@@ -6,8 +6,7 @@ const os = std.os;
pub fn main() !void {
var stdout_file = try io.getStdOut();
- var stdout_file_stream = io.FileOutStream.init(stdout_file);
- const stdout = &stdout_file_stream.stream;
+ const stdout = &stdout_file.outStream().stream;
try stdout.print("Welcome to the Guess Number Game in Zig.\n");
diff --git a/src-self-hosted/errmsg.zig b/src-self-hosted/errmsg.zig
index 6cf29b9441..0e552fde7e 100644
--- a/src-self-hosted/errmsg.zig
+++ b/src-self-hosted/errmsg.zig
@@ -278,7 +278,7 @@ pub const Msg = struct {
Color.On => true,
Color.Off => false,
};
- var stream = &std.io.FileOutStream.init(file).stream;
+ var stream = &file.outStream().stream;
return msg.printToStream(stream, color_on);
}
};
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 5e292ff8b2..bbfc0125f4 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -30,7 +30,7 @@ pub const LibCInstallation = struct {
self: *LibCInstallation,
allocator: *std.mem.Allocator,
libc_file: []const u8,
- stderr: *std.io.OutStream(std.io.FileOutStream.Error),
+ stderr: *std.io.OutStream(std.os.File.WriteError),
) !void {
self.initEmpty();
@@ -100,7 +100,7 @@ pub const LibCInstallation = struct {
}
}
- pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(std.io.FileOutStream.Error)) !void {
+ pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(std.os.File.WriteError)) !void {
@setEvalBranchQuota(4000);
try out.print(
\\# The directory that contains `stdlib.h`.
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index 6aa5f067ef..6d4f20e557 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -21,8 +21,8 @@ const errmsg = @import("errmsg.zig");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
var stderr_file: os.File = undefined;
-var stderr: *io.OutStream(io.FileOutStream.Error) = undefined;
-var stdout: *io.OutStream(io.FileOutStream.Error) = undefined;
+var stderr: *io.OutStream(os.File.WriteError) = undefined;
+var stdout: *io.OutStream(os.File.WriteError) = undefined;
const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
@@ -55,11 +55,11 @@ pub fn main() !void {
const allocator = std.heap.c_allocator;
var stdout_file = try std.io.getStdOut();
- var stdout_out_stream = std.io.FileOutStream.init(stdout_file);
+ var stdout_out_stream = stdout_file.outStream();
stdout = &stdout_out_stream.stream;
stderr_file = try std.io.getStdErr();
- var stderr_out_stream = std.io.FileOutStream.init(stderr_file);
+ var stderr_out_stream = stderr_file.outStream();
stderr = &stderr_out_stream.stream;
const args = try os.argsAlloc(allocator);
@@ -619,7 +619,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
}
var stdin_file = try io.getStdIn();
- var stdin = io.FileInStream.init(stdin_file);
+ var stdin = stdin_file.inStream();
const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);
defer allocator.free(source_code);
diff --git a/std/atomic/queue.zig b/std/atomic/queue.zig
index eea77d5534..796120eee4 100644
--- a/std/atomic/queue.zig
+++ b/std/atomic/queue.zig
@@ -114,7 +114,7 @@ pub fn Queue(comptime T: type) type {
fn dumpRecursive(optional_node: ?*Node, indent: usize) void {
var stderr_file = std.io.getStdErr() catch return;
- const stderr = &std.io.FileOutStream.init(stderr_file).stream;
+ const stderr = &stderr_file.outStream().stream;
stderr.writeByteNTimes(' ', indent) catch return;
if (optional_node) |node| {
std.debug.warn("0x{x}={}\n", @ptrToInt(node), node.data);
diff --git a/std/coff.zig b/std/coff.zig
index bf5a93ef30..6a1aa34b46 100644
--- a/std/coff.zig
+++ b/std/coff.zig
@@ -41,7 +41,7 @@ pub const Coff = struct {
pub fn loadHeader(self: *Coff) !void {
const pe_pointer_offset = 0x3C;
- var file_stream = io.FileInStream.init(self.in_file);
+ var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var magic: [2]u8 = undefined;
@@ -77,7 +77,7 @@ pub const Coff = struct {
try self.loadOptionalHeader(&file_stream);
}
- fn loadOptionalHeader(self: *Coff, file_stream: *io.FileInStream) !void {
+ fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
const in = &file_stream.stream;
self.pe_header.magic = try in.readIntLe(u16);
// For now we're only interested in finding the reference to the .pdb,
@@ -115,7 +115,7 @@ pub const Coff = struct {
const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
try self.in_file.seekTo(file_offset + debug_dir.size);
- var file_stream = io.FileInStream.init(self.in_file);
+ var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var cv_signature: [4]u8 = undefined; // CodeView signature
@@ -146,7 +146,7 @@ pub const Coff = struct {
self.sections = ArrayList(Section).init(self.allocator);
- var file_stream = io.FileInStream.init(self.in_file);
+ var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var name: [8]u8 = undefined;
diff --git a/std/crypto/throughput_test.zig b/std/crypto/throughput_test.zig
index 8894b4fff4..10ef1bcd48 100644
--- a/std/crypto/throughput_test.zig
+++ b/std/crypto/throughput_test.zig
@@ -130,7 +130,7 @@ fn printPad(stdout: var, s: []const u8) !void {
pub fn main() !void {
var stdout_file = try std.io.getStdOut();
- var stdout_out_stream = std.io.FileOutStream.init(stdout_file);
+ var stdout_out_stream = stdout_file.outStream();
const stdout = &stdout_out_stream.stream;
var buffer: [1024]u8 = undefined;
diff --git a/std/debug/index.zig b/std/debug/index.zig
index 4a8ee365ba..edd47b0ab1 100644
--- a/std/debug/index.zig
+++ b/std/debug/index.zig
@@ -34,10 +34,10 @@ const Module = struct {
/// Tries to write to stderr, unbuffered, and ignores any error returned.
/// Does not append a newline.
var stderr_file: os.File = undefined;
-var stderr_file_out_stream: io.FileOutStream = undefined;
+var stderr_file_out_stream: os.File.OutStream = undefined;
/// TODO multithreaded awareness
-var stderr_stream: ?*io.OutStream(io.FileOutStream.Error) = null;
+var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
var stderr_mutex = std.Mutex.init();
pub fn warn(comptime fmt: []const u8, args: ...) void {
const held = stderr_mutex.acquire();
@@ -46,12 +46,12 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
stderr.print(fmt, args) catch return;
}
-pub fn getStderrStream() !*io.OutStream(io.FileOutStream.Error) {
+pub fn getStderrStream() !*io.OutStream(os.File.WriteError) {
if (stderr_stream) |st| {
return st;
} else {
stderr_file = try io.getStdErr();
- stderr_file_out_stream = io.FileOutStream.init(stderr_file);
+ stderr_file_out_stream = stderr_file.outStream();
const st = &stderr_file_out_stream.stream;
stderr_stream = st;
return st;
@@ -876,7 +876,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
}
pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr {
- var file_stream = io.FileInStream.init(elf.in_file);
+ var file_stream = elf.in_file.inStream();
const in = &file_stream.stream;
section_loop: for (elf.section_headers) |*elf_section| {
@@ -1068,7 +1068,7 @@ pub const DebugInfo = switch (builtin.os) {
}
pub fn readString(self: *DebugInfo) ![]u8 {
- var in_file_stream = io.FileInStream.init(self.self_exe_file);
+ var in_file_stream = self.self_exe_file.inStream();
const in_stream = &in_file_stream.stream;
return readStringRaw(self.allocator(), in_stream);
}
@@ -1405,7 +1405,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
const in_file = st.self_exe_file;
- var in_file_stream = io.FileInStream.init(in_file);
+ var in_file_stream = in_file.inStream();
const in_stream = &in_file_stream.stream;
var result = AbbrevTable.init(st.allocator());
while (true) {
@@ -1456,7 +1456,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
const in_file = st.self_exe_file;
- var in_file_stream = io.FileInStream.init(in_file);
+ var in_file_stream = in_file.inStream();
const in_stream = &in_file_stream.stream;
const abbrev_code = try readULeb128(in_stream);
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
@@ -1682,7 +1682,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
var this_offset = di.debug_line.offset;
var this_index: usize = 0;
- var in_file_stream = io.FileInStream.init(in_file);
+ var in_file_stream = in_file.inStream();
const in_stream = &in_file_stream.stream;
while (this_offset < debug_line_end) : (this_index += 1) {
@@ -1857,7 +1857,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
var this_unit_offset = st.debug_info.offset;
var cu_index: usize = 0;
- var in_file_stream = io.FileInStream.init(st.self_exe_file);
+ var in_file_stream = st.self_exe_file.inStream();
const in_stream = &in_file_stream.stream;
while (this_unit_offset < debug_info_end) {
@@ -1923,7 +1923,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
}
fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
- var in_file_stream = io.FileInStream.init(st.self_exe_file);
+ var in_file_stream = st.self_exe_file.inStream();
const in_stream = &in_file_stream.stream;
for (st.compile_unit_list.toSlice()) |*compile_unit| {
if (compile_unit.pc_range) |range| {
diff --git a/std/elf.zig b/std/elf.zig
index a3a72dc728..af74f3e052 100644
--- a/std/elf.zig
+++ b/std/elf.zig
@@ -381,7 +381,7 @@ pub const Elf = struct {
elf.in_file = file;
elf.auto_close_stream = false;
- var file_stream = io.FileInStream.init(elf.in_file);
+ var file_stream = elf.in_file.inStream();
const in = &file_stream.stream;
var magic: [4]u8 = undefined;
@@ -525,7 +525,7 @@ pub const Elf = struct {
}
pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
- var file_stream = io.FileInStream.init(elf.in_file);
+ var file_stream = elf.in_file.inStream();
const in = &file_stream.stream;
section_loop: for (elf.section_headers) |*elf_section| {
diff --git a/std/event.zig b/std/event.zig
index 56c5223ba3..8409cc5c00 100644
--- a/std/event.zig
+++ b/std/event.zig
@@ -6,6 +6,7 @@ pub const Locked = @import("event/locked.zig").Locked;
pub const RwLock = @import("event/rwlock.zig").RwLock;
pub const RwLocked = @import("event/rwlocked.zig").RwLocked;
pub const Loop = @import("event/loop.zig").Loop;
+pub const io = @import("event/io.zig");
pub const fs = @import("event/fs.zig");
pub const net = @import("event/net.zig");
@@ -14,6 +15,7 @@ test "import event tests" {
_ = @import("event/fs.zig");
_ = @import("event/future.zig");
_ = @import("event/group.zig");
+ _ = @import("event/io.zig");
_ = @import("event/lock.zig");
_ = @import("event/locked.zig");
_ = @import("event/rwlock.zig");
diff --git a/std/event/fs.zig b/std/event/fs.zig
index bde5a306b6..7f96ae22b6 100644
--- a/std/event/fs.zig
+++ b/std/event/fs.zig
@@ -1246,9 +1246,7 @@ pub fn Watch(comptime V: type) type {
os.linux.EPOLLET | os.linux.EPOLLIN,
) catch unreachable)) catch |err| {
const transformed_err = switch (err) {
- error.InvalidFileDescriptor => unreachable,
error.FileDescriptorAlreadyPresentInSet => unreachable,
- error.InvalidSyscall => unreachable,
error.OperationCausesCircularLoop => unreachable,
error.FileDescriptorNotRegistered => unreachable,
error.SystemResources => error.SystemResources,
diff --git a/std/event/io.zig b/std/event/io.zig
new file mode 100644
index 0000000000..13bff66459
--- /dev/null
+++ b/std/event/io.zig
@@ -0,0 +1,48 @@
+const std = @import("../index.zig");
+const builtin = @import("builtin");
+const Allocator = std.mem.Allocator;
+const assert = std.debug.assert;
+
+pub fn InStream(comptime ReadError: type) type {
+ return struct {
+ const Self = @This();
+ pub const Error = ReadError;
+
+ /// Return the number of bytes read. It may be less than buffer.len.
+ /// If the number of bytes read is 0, it means end of stream.
+ /// End of stream is not an error condition.
+ readFn: async<*Allocator> fn (self: *Self, buffer: []u8) Error!usize,
+
+ /// Return the number of bytes read. It may be less than buffer.len.
+ /// If the number of bytes read is 0, it means end of stream.
+ /// End of stream is not an error condition.
+ pub async fn read(self: *Self, buffer: []u8) !usize {
+ return await (async self.readFn(self, buffer) catch unreachable);
+ }
+
+ /// Same as `read` but end of stream returns `error.EndOfStream`.
+ pub async fn readFull(self: *Self, buf: []u8) !void {
+ var index: usize = 0;
+ while (index != buf.len) {
+ const amt_read = try await (async self.read(buf[index..]) catch unreachable);
+ if (amt_read == 0) return error.EndOfStream;
+ index += amt_read;
+ }
+ }
+
+ pub async fn readStruct(self: *Self, comptime T: type, ptr: *T) !void {
+ // Only extern and packed structs have defined in-memory layout.
+ comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
+ return await (async self.readFull(@sliceToBytes((*[1]T)(ptr)[0..])) catch unreachable);
+ }
+ };
+}
+
+pub fn OutStream(comptime WriteError: type) type {
+ return struct {
+ const Self = @This();
+ pub const Error = WriteError;
+
+ writeFn: async<*Allocator> fn (self: *Self, buffer: []u8) Error!void,
+ };
+}
diff --git a/std/event/net.zig b/std/event/net.zig
index c1e6e891cd..25aa85efb5 100644
--- a/std/event/net.zig
+++ b/std/event/net.zig
@@ -3,12 +3,12 @@ const builtin = @import("builtin");
const assert = std.debug.assert;
const event = std.event;
const mem = std.mem;
-const posix = std.os.posix;
-const windows = std.os.windows;
+const os = std.os;
+const posix = os.posix;
const Loop = std.event.Loop;
pub const Server = struct {
- handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, *const std.os.File) void,
+ handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, *const os.File) void,
loop: *Loop,
sockfd: ?i32,
@@ -40,17 +40,17 @@ pub const Server = struct {
pub fn listen(
self: *Server,
address: *const std.net.Address,
- handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, *const std.os.File) void,
+ handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, *const os.File) void,
) !void {
self.handleRequestFn = handleRequestFn;
- const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
- errdefer std.os.close(sockfd);
+ const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
+ errdefer os.close(sockfd);
self.sockfd = sockfd;
- try std.os.posixBind(sockfd, &address.os_addr);
- try std.os.posixListen(sockfd, posix.SOMAXCONN);
- self.listen_address = std.net.Address.initPosix(try std.os.posixGetSockName(sockfd));
+ try os.posixBind(sockfd, &address.os_addr);
+ try os.posixListen(sockfd, posix.SOMAXCONN);
+ self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd));
self.accept_coro = try async Server.handler(self);
errdefer cancel self.accept_coro.?;
@@ -63,19 +63,25 @@ pub const Server = struct {
/// Stop listening
pub fn close(self: *Server) void {
self.loop.linuxRemoveFd(self.sockfd.?);
- std.os.close(self.sockfd.?);
+ os.close(self.sockfd.?);
}
pub fn deinit(self: *Server) void {
if (self.accept_coro) |accept_coro| cancel accept_coro;
- if (self.sockfd) |sockfd| std.os.close(sockfd);
+ if (self.sockfd) |sockfd| os.close(sockfd);
}
pub async fn handler(self: *Server) void {
while (true) {
var accepted_addr: std.net.Address = undefined;
- if (std.os.posixAccept(self.sockfd.?, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| {
- var socket = std.os.File.openHandle(accepted_fd);
+ // TODO just inline the following function here and don't expose it as posixAsyncAccept
+ if (os.posixAsyncAccept(self.sockfd.?, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| {
+ if (accepted_fd == -1) {
+ // would block
+ suspend; // we will get resumed by epoll_wait in the event loop
+ continue;
+ }
+ var socket = os.File.openHandle(accepted_fd);
_ = async self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) {
error.OutOfMemory => {
socket.close();
@@ -83,22 +89,16 @@ pub const Server = struct {
},
};
} else |err| switch (err) {
- error.WouldBlock => {
- suspend; // we will get resumed by epoll_wait in the event loop
- continue;
- },
error.ProcessFdQuotaExceeded => {
- errdefer std.os.emfile_promise_queue.remove(&self.waiting_for_emfile_node);
+ errdefer os.emfile_promise_queue.remove(&self.waiting_for_emfile_node);
suspend {
self.waiting_for_emfile_node = PromiseNode.init(@handle());
- std.os.emfile_promise_queue.append(&self.waiting_for_emfile_node);
+ os.emfile_promise_queue.append(&self.waiting_for_emfile_node);
}
continue;
},
- error.ConnectionAborted, error.FileDescriptorClosed => continue,
+ error.ConnectionAborted => continue,
- error.PageFault => unreachable,
- error.InvalidSyscall => unreachable,
error.FileDescriptorNotASocket => unreachable,
error.OperationNotSupported => unreachable,
@@ -111,64 +111,161 @@ pub const Server = struct {
};
pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {
- const sockfd = try std.os.posixSocket(
+ const sockfd = try os.posixSocket(
posix.AF_UNIX,
posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK,
0,
);
- errdefer std.os.close(sockfd);
+ errdefer os.close(sockfd);
- var sock_addr = posix.sockaddr{
- .un = posix.sockaddr_un{
- .family = posix.AF_UNIX,
- .path = undefined,
- },
+ var sock_addr = posix.sockaddr_un{
+ .family = posix.AF_UNIX,
+ .path = undefined,
};
- if (path.len > @typeOf(sock_addr.un.path).len) return error.NameTooLong;
- mem.copy(u8, sock_addr.un.path[0..], path);
+ if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong;
+ mem.copy(u8, sock_addr.path[0..], path);
const size = @intCast(u32, @sizeOf(posix.sa_family_t) + path.len);
- try std.os.posixConnectAsync(sockfd, &sock_addr, size);
+ try os.posixConnectAsync(sockfd, &sock_addr, size);
try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
- try std.os.posixGetSockOptConnectError(sockfd);
+ try os.posixGetSockOptConnectError(sockfd);
return sockfd;
}
-pub async fn socketRead(loop: *std.event.Loop, fd: i32, buffer: []u8) !void {
- while (true) {
- return std.os.posixRead(fd, buffer) catch |err| switch (err) {
- error.WouldBlock => {
- try await try async loop.linuxWaitFd(fd, std.os.posix.EPOLLET | std.os.posix.EPOLLIN);
- continue;
- },
- else => return err,
- };
- }
+pub const ReadError = error{
+ SystemResources,
+ Unexpected,
+ UserResourceLimitReached,
+ InputOutput,
+
+ FileDescriptorNotRegistered, // TODO remove this possibility
+ OperationCausesCircularLoop, // TODO remove this possibility
+ FileDescriptorAlreadyPresentInSet, // TODO remove this possibility
+ FileDescriptorIncompatibleWithEpoll, // TODO remove this possibility
+};
+
+/// returns number of bytes read. 0 means EOF.
+pub async fn read(loop: *std.event.Loop, fd: os.FileHandle, buffer: []u8) ReadError!usize {
+ const iov = posix.iovec{
+ .iov_base = buffer.ptr,
+ .iov_len = buffer.len,
+ };
+ const iovs: *const [1]posix.iovec = &iov;
+ return await (async readvPosix(loop, fd, iovs, 1) catch unreachable);
}
-pub async fn socketWrite(loop: *std.event.Loop, fd: i32, buffer: []const u8) !void {
+
+pub const WriteError = error{};
+
+pub async fn write(loop: *std.event.Loop, fd: os.FileHandle, buffer: []const u8) WriteError!void {
+ const iov = posix.iovec_const{
+ .iov_base = buffer.ptr,
+ .iov_len = buffer.len,
+ };
+ const iovs: *const [1]posix.iovec_const = &iov;
+ return await (async writevPosix(loop, fd, iovs, 1) catch unreachable);
+}
+
+pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, count: usize) !void {
while (true) {
- return std.os.posixWrite(fd, buffer) catch |err| switch (err) {
- error.WouldBlock => {
- try await try async loop.linuxWaitFd(fd, std.os.posix.EPOLLET | std.os.posix.EPOLLOUT);
- continue;
+ switch (builtin.os) {
+ builtin.Os.macosx, builtin.Os.linux => {
+ const rc = posix.writev(fd, iov, count);
+ const err = posix.getErrno(rc);
+ switch (err) {
+ 0 => return,
+ posix.EINTR => continue,
+ posix.ESPIPE => unreachable,
+ posix.EINVAL => unreachable,
+ posix.EFAULT => unreachable,
+ posix.EAGAIN => {
+ try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLOUT) catch unreachable);
+ continue;
+ },
+ posix.EBADF => unreachable, // always a race condition
+ posix.EDESTADDRREQ => unreachable, // connect was never called
+ posix.EDQUOT => unreachable,
+ posix.EFBIG => unreachable,
+ posix.EIO => return error.InputOutput,
+ posix.ENOSPC => unreachable,
+ posix.EPERM => return error.AccessDenied,
+ posix.EPIPE => unreachable,
+ else => return os.unexpectedErrorPosix(err),
+ }
},
- else => return err,
- };
+ else => @compileError("Unsupported OS"),
+ }
}
}
-pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File {
- var address = _address.*; // TODO https://github.com/ziglang/zig/issues/733
+/// returns number of bytes read. 0 means EOF.
+pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, count: usize) !usize {
+ while (true) {
+ switch (builtin.os) {
+ builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => {
+ const rc = posix.readv(fd, iov, count);
+ const err = posix.getErrno(rc);
+ switch (err) {
+ 0 => return rc,
+ posix.EINTR => continue,
+ posix.EINVAL => unreachable,
+ posix.EFAULT => unreachable,
+ posix.EAGAIN => {
+ try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLIN) catch unreachable);
+ continue;
+ },
+ posix.EBADF => unreachable, // always a race condition
+ posix.EIO => return error.InputOutput,
+ posix.EISDIR => unreachable,
+ posix.ENOBUFS => return error.SystemResources,
+ posix.ENOMEM => return error.SystemResources,
+ else => return os.unexpectedErrorPosix(err),
+ }
+ },
+ else => @compileError("Unsupported OS"),
+ }
+ }
+}
- const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
- errdefer std.os.close(sockfd);
+pub async fn writev(loop: *Loop, fd: os.FileHandle, data: []const []const u8) !void {
+ const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
+ defer loop.allocator.free(iovecs);
- try std.os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in));
+ for (data) |buf, i| {
+ iovecs[i] = os.posix.iovec_const{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ };
+ }
+
+ return await (async writevPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);
+}
+
+pub async fn readv(loop: *Loop, fd: os.FileHandle, data: []const []u8) !usize {
+ const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
+ defer loop.allocator.free(iovecs);
+
+ for (data) |buf, i| {
+ iovecs[i] = os.posix.iovec{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ };
+ }
+
+ return await (async readvPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);
+}
+
+pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
+ var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
+
+ const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
+ errdefer os.close(sockfd);
+
+ try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in));
try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
- try std.os.posixGetSockOptConnectError(sockfd);
+ try os.posixGetSockOptConnectError(sockfd);
- return std.os.File.openHandle(sockfd);
+ return os.File.openHandle(sockfd);
}
test "listen on a port, send bytes, receive bytes" {
@@ -181,9 +278,9 @@ test "listen on a port, send bytes, receive bytes" {
tcp_server: Server,
const Self = @This();
- async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: *const std.os.File) void {
+ async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: *const os.File) void {
const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
- var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
+ var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/1592
defer socket.close();
// TODO guarantee elision of this allocation
const next_handler = async errorableHandler(self, _addr, socket) catch unreachable;
@@ -194,12 +291,11 @@ test "listen on a port, send bytes, receive bytes" {
cancel @handle();
}
}
- async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: std.os.File) !void {
- const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733
- var socket = _socket; // TODO https://github.com/ziglang/zig/issues/733
+ async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: os.File) !void {
+ const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592
+ var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
- var adapter = std.io.FileOutStream.init(socket);
- var stream = &adapter.stream;
+ const stream = &socket.outStream().stream;
try stream.print("hello from server\n");
}
};
@@ -230,3 +326,47 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv
assert(mem.eql(u8, msg, "hello from server\n"));
server.close();
}
+
+pub const OutStream = struct {
+ fd: os.FileHandle,
+ stream: Stream,
+ loop: *Loop,
+
+ pub const Error = WriteError;
+ pub const Stream = event.io.OutStream(Error);
+
+ pub fn init(loop: *Loop, fd: os.FileHandle) OutStream {
+ return OutStream{
+ .fd = fd,
+ .loop = loop,
+ .stream = Stream{ .writeFn = writeFn },
+ };
+ }
+
+ async<*mem.Allocator> fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
+ const self = @fieldParentPtr(OutStream, "stream", out_stream);
+ return await (async write(self.loop, self.fd, bytes) catch unreachable);
+ }
+};
+
+pub const InStream = struct {
+ fd: os.FileHandle,
+ stream: Stream,
+ loop: *Loop,
+
+ pub const Error = ReadError;
+ pub const Stream = event.io.InStream(Error);
+
+ pub fn init(loop: *Loop, fd: os.FileHandle) InStream {
+ return InStream{
+ .fd = fd,
+ .loop = loop,
+ .stream = Stream{ .readFn = readFn },
+ };
+ }
+
+ async<*mem.Allocator> fn readFn(in_stream: *Stream, bytes: []u8) Error!usize {
+ const self = @fieldParentPtr(InStream, "stream", in_stream);
+ return await (async read(self.loop, self.fd, bytes) catch unreachable);
+ }
+};
diff --git a/std/io.zig b/std/io.zig
index c10fdcbbe2..3d20d8b9dc 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -32,48 +32,6 @@ pub fn getStdIn() GetStdIoErrs!File {
return File.openHandle(handle);
}
-/// Implementation of InStream trait for File
-pub const FileInStream = struct {
- file: File,
- stream: Stream,
-
- pub const Error = @typeOf(File.read).ReturnType.ErrorSet;
- pub const Stream = InStream(Error);
-
- pub fn init(file: File) FileInStream {
- return FileInStream{
- .file = file,
- .stream = Stream{ .readFn = readFn },
- };
- }
-
- fn readFn(in_stream: *Stream, buffer: []u8) Error!usize {
- const self = @fieldParentPtr(FileInStream, "stream", in_stream);
- return self.file.read(buffer);
- }
-};
-
-/// Implementation of OutStream trait for File
-pub const FileOutStream = struct {
- file: File,
- stream: Stream,
-
- pub const Error = File.WriteError;
- pub const Stream = OutStream(Error);
-
- pub fn init(file: File) FileOutStream {
- return FileOutStream{
- .file = file,
- .stream = Stream{ .writeFn = writeFn },
- };
- }
-
- fn writeFn(out_stream: *Stream, bytes: []const u8) !void {
- const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
- return self.file.write(bytes);
- }
-};
-
pub fn InStream(comptime ReadError: type) type {
return struct {
const Self = @This();
@@ -280,7 +238,7 @@ pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptim
const buf = try allocator.alignedAlloc(u8, A, size);
errdefer allocator.free(buf);
- var adapter = FileInStream.init(file);
+ var adapter = file.inStream();
try adapter.stream.readNoEof(buf[0..size]);
return buf;
}
@@ -577,8 +535,8 @@ pub const BufferOutStream = struct {
pub const BufferedAtomicFile = struct {
atomic_file: os.AtomicFile,
- file_stream: FileOutStream,
- buffered_stream: BufferedOutStream(FileOutStream.Error),
+ file_stream: os.File.OutStream,
+ buffered_stream: BufferedOutStream(os.File.WriteError),
pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
// TODO with well defined copy elision we don't need this allocation
@@ -592,8 +550,8 @@ pub const BufferedAtomicFile = struct {
self.atomic_file = try os.AtomicFile.init(allocator, dest_path, os.File.default_mode);
errdefer self.atomic_file.deinit();
- self.file_stream = FileOutStream.init(self.atomic_file.file);
- self.buffered_stream = BufferedOutStream(FileOutStream.Error).init(&self.file_stream.stream);
+ self.file_stream = self.atomic_file.file.outStream();
+ self.buffered_stream = BufferedOutStream(os.File.WriteError).init(&self.file_stream.stream);
return self;
}
@@ -609,7 +567,7 @@ pub const BufferedAtomicFile = struct {
try self.atomic_file.finish();
}
- pub fn stream(self: *BufferedAtomicFile) *OutStream(FileOutStream.Error) {
+ pub fn stream(self: *BufferedAtomicFile) *OutStream(os.File.WriteError) {
return &self.buffered_stream.stream;
}
};
@@ -622,7 +580,7 @@ test "import io tests" {
pub fn readLine(buf: []u8) !usize {
var stdin = getStdIn() catch return error.StdInUnavailable;
- var adapter = FileInStream.init(stdin);
+ var adapter = stdin.inStream();
var stream = &adapter.stream;
var index: usize = 0;
while (true) {
@@ -642,3 +600,5 @@ pub fn readLine(buf: []u8) !usize {
}
}
}
+
+
diff --git a/std/io_test.zig b/std/io_test.zig
index 7403c96994..5224199527 100644
--- a/std/io_test.zig
+++ b/std/io_test.zig
@@ -19,8 +19,8 @@ test "write a file, read it, then delete it" {
var file = try os.File.openWrite(tmp_file_name);
defer file.close();
- var file_out_stream = io.FileOutStream.init(file);
- var buf_stream = io.BufferedOutStream(io.FileOutStream.Error).init(&file_out_stream.stream);
+ var file_out_stream = file.outStream();
+ var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
const st = &buf_stream.stream;
try st.print("begin");
try st.write(data[0..]);
@@ -35,8 +35,8 @@ test "write a file, read it, then delete it" {
const expected_file_size = "begin".len + data.len + "end".len;
assert(file_size == expected_file_size);
- var file_in_stream = io.FileInStream.init(file);
- var buf_stream = io.BufferedInStream(io.FileInStream.Error).init(&file_in_stream.stream);
+ var file_in_stream = file.inStream();
+ var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
const st = &buf_stream.stream;
const contents = try st.readAllAlloc(allocator, 2 * 1024);
defer allocator.free(contents);
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index 8b76a3cb9e..5c02f1ebe0 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -211,8 +211,8 @@ pub const ChildProcess = struct {
defer Buffer.deinit(&stdout);
defer Buffer.deinit(&stderr);
- var stdout_file_in_stream = io.FileInStream.init(child.stdout.?);
- var stderr_file_in_stream = io.FileInStream.init(child.stderr.?);
+ var stdout_file_in_stream = child.stdout.?.inStream();
+ var stderr_file_in_stream = child.stderr.?.inStream();
try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
diff --git a/std/os/file.zig b/std/os/file.zig
index 020a5dca54..4a98dbcfa5 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -1,6 +1,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const os = std.os;
+const io = std.io;
const mem = std.mem;
const math = std.math;
const assert = std.debug.assert;
@@ -368,7 +369,6 @@ pub const File = struct {
FileClosed,
InputOutput,
IsDir,
- WouldBlock,
SystemResources,
Unexpected,
@@ -385,7 +385,7 @@ pub const File = struct {
posix.EINTR => continue,
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
- posix.EAGAIN => return error.WouldBlock,
+ posix.EAGAIN => unreachable,
posix.EBADF => return error.FileClosed,
posix.EIO => return error.InputOutput,
posix.EISDIR => return error.IsDir,
@@ -431,4 +431,46 @@ pub const File = struct {
@compileError("Unsupported OS");
}
}
+
+ pub fn inStream(file: File) InStream {
+ return InStream{
+ .file = file,
+ .stream = InStream.Stream{ .readFn = InStream.readFn },
+ };
+ }
+
+ pub fn outStream(file: File) OutStream {
+ return OutStream{
+ .file = file,
+ .stream = OutStream.Stream{ .writeFn = OutStream.writeFn },
+ };
+ }
+
+ /// Implementation of io.InStream trait for File
+ pub const InStream = struct {
+ file: File,
+ stream: Stream,
+
+ pub const Error = ReadError;
+ pub const Stream = io.InStream(Error);
+
+ fn readFn(in_stream: *Stream, buffer: []u8) Error!usize {
+ const self = @fieldParentPtr(InStream, "stream", in_stream);
+ return self.file.read(buffer);
+ }
+ };
+
+ /// Implementation of io.OutStream trait for File
+ pub const OutStream = struct {
+ file: File,
+ stream: Stream,
+
+ pub const Error = WriteError;
+ pub const Stream = io.OutStream(Error);
+
+ fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
+ const self = @fieldParentPtr(OutStream, "stream", out_stream);
+ return self.file.write(bytes);
+ }
+ };
};
diff --git a/std/os/index.zig b/std/os/index.zig
index a53d1d2050..778e3b9655 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -242,8 +242,8 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
return switch (err) {
posix.EINTR => continue,
posix.EINVAL, posix.EFAULT => unreachable,
- posix.EAGAIN => error.WouldBlock,
- posix.EBADF => error.FileClosed,
+ posix.EAGAIN => unreachable,
+ posix.EBADF => unreachable, // always a race condition
posix.EIO => error.InputOutput,
posix.EISDIR => error.IsDir,
posix.ENOBUFS, posix.ENOMEM => error.SystemResources,
@@ -284,8 +284,8 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
posix.ESPIPE => unreachable, // fd is not seekable
- posix.EAGAIN => return error.WouldBlock,
- posix.EBADF => return error.FileClosed,
+ posix.EAGAIN => unreachable, // use posixAsyncPReadV for non blocking
+ posix.EBADF => unreachable, // always a race condition
posix.EIO => return error.InputOutput,
posix.EISDIR => return error.IsDir,
posix.ENOBUFS => return error.SystemResources,
@@ -302,8 +302,8 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
posix.EINTR => continue,
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
- posix.EAGAIN => return error.WouldBlock,
- posix.EBADF => return error.FileClosed,
+ posix.EAGAIN => unreachable, // use posixAsyncPReadV for non blocking
+ posix.EBADF => unreachable, // always a race condition
posix.EIO => return error.InputOutput,
posix.EISDIR => return error.IsDir,
posix.ENOBUFS => return error.SystemResources,
@@ -316,9 +316,6 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
}
pub const PosixWriteError = error{
- WouldBlock,
- FileClosed,
- DestinationAddressRequired,
DiskQuota,
FileTooBig,
InputOutput,
@@ -349,9 +346,9 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
posix.EINTR => continue,
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
- posix.EAGAIN => return PosixWriteError.WouldBlock,
- posix.EBADF => return PosixWriteError.FileClosed,
- posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
+ posix.EAGAIN => unreachable, // use posixAsyncWrite for non-blocking
+ posix.EBADF => unreachable, // always a race condition
+ posix.EDESTADDRREQ => unreachable, // connect was never called
posix.EDQUOT => return PosixWriteError.DiskQuota,
posix.EFBIG => return PosixWriteError.FileTooBig,
posix.EIO => return PosixWriteError.InputOutput,
@@ -391,9 +388,9 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off
posix.ESPIPE => unreachable, // fd is not seekable
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
- posix.EAGAIN => return PosixWriteError.WouldBlock,
- posix.EBADF => return PosixWriteError.FileClosed,
- posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
+ posix.EAGAIN => unreachable, // use posixAsyncPWriteV for non-blocking
+ posix.EBADF => unreachable, // always a race condition
+ posix.EDESTADDRREQ => unreachable, // connect was never called
posix.EDQUOT => return PosixWriteError.DiskQuota,
posix.EFBIG => return PosixWriteError.FileTooBig,
posix.EIO => return PosixWriteError.InputOutput,
@@ -412,9 +409,9 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off
posix.EINTR => continue,
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
- posix.EAGAIN => return PosixWriteError.WouldBlock,
- posix.EBADF => return PosixWriteError.FileClosed,
- posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
+ posix.EAGAIN => unreachable, // use posixAsyncPWriteV for non-blocking
+ posix.EBADF => unreachable, // always a race condition
+ posix.EDESTADDRREQ => unreachable, // connect was never called
posix.EDQUOT => return PosixWriteError.DiskQuota,
posix.EFBIG => return PosixWriteError.FileTooBig,
posix.EIO => return PosixWriteError.InputOutput,
@@ -2287,22 +2284,9 @@ pub const PosixBindError = error{
/// use. See the discussion of /proc/sys/net/ipv4/ip_local_port_range ip(7).
AddressInUse,
- /// sockfd is not a valid file descriptor.
- InvalidFileDescriptor,
-
- /// The socket is already bound to an address, or addrlen is wrong, or addr is not
- /// a valid address for this socket's domain.
- InvalidSocketOrAddress,
-
- /// The file descriptor sockfd does not refer to a socket.
- FileDescriptorNotASocket,
-
/// A nonexistent interface was requested or the requested address was not local.
AddressNotAvailable,
- /// addr points outside the user's accessible address space.
- PageFault,
-
/// Too many symbolic links were encountered in resolving addr.
SymLinkLoop,
@@ -2333,11 +2317,11 @@ pub fn posixBind(fd: i32, addr: *const posix.sockaddr) PosixBindError!void {
0 => return,
posix.EACCES => return PosixBindError.AccessDenied,
posix.EADDRINUSE => return PosixBindError.AddressInUse,
- posix.EBADF => return PosixBindError.InvalidFileDescriptor,
- posix.EINVAL => return PosixBindError.InvalidSocketOrAddress,
- posix.ENOTSOCK => return PosixBindError.FileDescriptorNotASocket,
+ posix.EBADF => unreachable, // always a race condition if this error is returned
+ posix.EINVAL => unreachable,
+ posix.ENOTSOCK => unreachable,
posix.EADDRNOTAVAIL => return PosixBindError.AddressNotAvailable,
- posix.EFAULT => return PosixBindError.PageFault,
+ posix.EFAULT => unreachable,
posix.ELOOP => return PosixBindError.SymLinkLoop,
posix.ENAMETOOLONG => return PosixBindError.NameTooLong,
posix.ENOENT => return PosixBindError.FileNotFound,
@@ -2356,9 +2340,6 @@ const PosixListenError = error{
/// use. See the discussion of /proc/sys/net/ipv4/ip_local_port_range in ip(7).
AddressInUse,
- /// The argument sockfd is not a valid file descriptor.
- InvalidFileDescriptor,
-
/// The file descriptor sockfd does not refer to a socket.
FileDescriptorNotASocket,
@@ -2375,7 +2356,7 @@ pub fn posixListen(sockfd: i32, backlog: u32) PosixListenError!void {
switch (err) {
0 => return,
posix.EADDRINUSE => return PosixListenError.AddressInUse,
- posix.EBADF => return PosixListenError.InvalidFileDescriptor,
+ posix.EBADF => unreachable,
posix.ENOTSOCK => return PosixListenError.FileDescriptorNotASocket,
posix.EOPNOTSUPP => return PosixListenError.OperationNotSupported,
else => return unexpectedErrorPosix(err),
@@ -2383,21 +2364,8 @@ pub fn posixListen(sockfd: i32, backlog: u32) PosixListenError!void {
}
pub const PosixAcceptError = error{
- /// The socket is marked nonblocking and no connections are present to be accepted.
- WouldBlock,
-
- /// sockfd is not an open file descriptor.
- FileDescriptorClosed,
-
ConnectionAborted,
- /// The addr argument is not in a writable part of the user address space.
- PageFault,
-
- /// Socket is not listening for connections, or addrlen is invalid (e.g., is negative),
- /// or invalid value in flags.
- InvalidSyscall,
-
/// The per-process limit on the number of open file descriptors has been reached.
ProcessFdQuotaExceeded,
@@ -2433,14 +2401,43 @@ pub fn posixAccept(fd: i32, addr: *posix.sockaddr, flags: u32) PosixAcceptError!
posix.EINTR => continue,
else => return unexpectedErrorPosix(err),
- posix.EAGAIN => return PosixAcceptError.WouldBlock,
- posix.EBADF => return PosixAcceptError.FileDescriptorClosed,
+ posix.EAGAIN => unreachable, // use posixAsyncAccept for non-blocking
+ posix.EBADF => unreachable, // always a race condition
posix.ECONNABORTED => return PosixAcceptError.ConnectionAborted,
- posix.EFAULT => return PosixAcceptError.PageFault,
- posix.EINVAL => return PosixAcceptError.InvalidSyscall,
+ posix.EFAULT => unreachable,
+ posix.EINVAL => unreachable,
posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded,
posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded,
- posix.ENOBUFS, posix.ENOMEM => return PosixAcceptError.SystemResources,
+ posix.ENOBUFS => return PosixAcceptError.SystemResources,
+ posix.ENOMEM => return PosixAcceptError.SystemResources,
+ posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket,
+ posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported,
+ posix.EPROTO => return PosixAcceptError.ProtocolFailure,
+ posix.EPERM => return PosixAcceptError.BlockedByFirewall,
+ }
+ }
+}
+
+/// Returns -1 if would block.
+pub fn posixAsyncAccept(fd: i32, addr: *posix.sockaddr, flags: u32) PosixAcceptError!i32 {
+ while (true) {
+ var sockaddr_size = u32(@sizeOf(posix.sockaddr));
+ const rc = posix.accept4(fd, addr, &sockaddr_size, flags);
+ const err = posix.getErrno(rc);
+ switch (err) {
+ 0 => return @intCast(i32, rc),
+ posix.EINTR => continue,
+ else => return unexpectedErrorPosix(err),
+
+ posix.EAGAIN => return -1,
+ posix.EBADF => unreachable, // always a race condition
+ posix.ECONNABORTED => return PosixAcceptError.ConnectionAborted,
+ posix.EFAULT => unreachable,
+ posix.EINVAL => unreachable,
+ posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded,
+ posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded,
+ posix.ENOBUFS => return PosixAcceptError.SystemResources,
+ posix.ENOMEM => return PosixAcceptError.SystemResources,
posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket,
posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported,
posix.EPROTO => return PosixAcceptError.ProtocolFailure,
@@ -2450,9 +2447,6 @@ pub fn posixAccept(fd: i32, addr: *posix.sockaddr, flags: u32) PosixAcceptError!
}
pub const LinuxEpollCreateError = error{
- /// Invalid value specified in flags.
- InvalidSyscall,
-
/// The per-user limit on the number of epoll instances imposed by
/// /proc/sys/fs/epoll/max_user_instances was encountered. See epoll(7) for further
/// details.
@@ -2476,7 +2470,7 @@ pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 {
0 => return @intCast(i32, rc),
else => return unexpectedErrorPosix(err),
- posix.EINVAL => return LinuxEpollCreateError.InvalidSyscall,
+ posix.EINVAL => unreachable,
posix.EMFILE => return LinuxEpollCreateError.ProcessFdQuotaExceeded,
posix.ENFILE => return LinuxEpollCreateError.SystemFdQuotaExceeded,
posix.ENOMEM => return LinuxEpollCreateError.SystemResources,
@@ -2484,22 +2478,10 @@ pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 {
}
pub const LinuxEpollCtlError = error{
- /// epfd or fd is not a valid file descriptor.
- InvalidFileDescriptor,
-
/// op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already registered
/// with this epoll instance.
FileDescriptorAlreadyPresentInSet,
- /// epfd is not an epoll file descriptor, or fd is the same as epfd, or the requested
- /// operation op is not supported by this interface, or
- /// An invalid event type was specified along with EPOLLEXCLUSIVE in events, or
- /// op was EPOLL_CTL_MOD and events included EPOLLEXCLUSIVE, or
- /// op was EPOLL_CTL_MOD and the EPOLLEXCLUSIVE flag has previously been applied to
- /// this epfd, fd pair, or
- /// EPOLLEXCLUSIVE was specified in event and fd refers to an epoll instance.
- InvalidSyscall,
-
/// fd refers to an epoll instance and this EPOLL_CTL_ADD operation would result in a
/// circular loop of epoll instances monitoring one another.
OperationCausesCircularLoop,
@@ -2531,9 +2513,9 @@ pub fn linuxEpollCtl(epfd: i32, op: u32, fd: i32, event: *linux.epoll_event) Lin
0 => return,
else => return unexpectedErrorPosix(err),
- posix.EBADF => return LinuxEpollCtlError.InvalidFileDescriptor,
+ posix.EBADF => unreachable, // always a race condition if this happens
posix.EEXIST => return LinuxEpollCtlError.FileDescriptorAlreadyPresentInSet,
- posix.EINVAL => return LinuxEpollCtlError.InvalidSyscall,
+ posix.EINVAL => unreachable,
posix.ELOOP => return LinuxEpollCtlError.OperationCausesCircularLoop,
posix.ENOENT => return LinuxEpollCtlError.FileDescriptorNotRegistered,
posix.ENOMEM => return LinuxEpollCtlError.SystemResources,
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index 6323c89dda..e00c664afa 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -793,6 +793,14 @@ pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
return syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset);
}
+pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
+ return syscall3(SYS_readv, @intCast(usize, fd), @ptrToInt(iov), count);
+}
+
+pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
+ return syscall3(SYS_writev, @intCast(usize, fd), @ptrToInt(iov), count);
+}
+
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
return syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset);
}
diff --git a/std/pdb.zig b/std/pdb.zig
index 3bb6c9d58d..6d23711949 100644
--- a/std/pdb.zig
+++ b/std/pdb.zig
@@ -482,7 +482,7 @@ const Msf = struct {
streams: []MsfStream,
fn openFile(self: *Msf, allocator: *mem.Allocator, file: os.File) !void {
- var file_stream = io.FileInStream.init(file);
+ var file_stream = file.inStream();
const in = &file_stream.stream;
var superblock: SuperBlock = undefined;
@@ -597,7 +597,7 @@ const MsfStream = struct {
.stream = Stream{ .readFn = readFn },
};
- var file_stream = io.FileInStream.init(file);
+ var file_stream = file.inStream();
const in = &file_stream.stream;
try file.seekTo(pos);
@@ -627,7 +627,7 @@ const MsfStream = struct {
var offset = self.pos % self.block_size;
try self.in_file.seekTo(block * self.block_size + offset);
- var file_stream = io.FileInStream.init(self.in_file);
+ var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var size: usize = 0;
diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig
index 8cf237f634..f227e02c71 100644
--- a/std/special/build_runner.zig
+++ b/std/special/build_runner.zig
@@ -48,16 +48,16 @@ pub fn main() !void {
var prefix: ?[]const u8 = null;
var stderr_file = io.getStdErr();
- var stderr_file_stream: io.FileOutStream = undefined;
+ var stderr_file_stream: os.File.OutStream = undefined;
var stderr_stream = if (stderr_file) |f| x: {
- stderr_file_stream = io.FileOutStream.init(f);
+ stderr_file_stream = f.outStream();
break :x &stderr_file_stream.stream;
} else |err| err;
var stdout_file = io.getStdOut();
- var stdout_file_stream: io.FileOutStream = undefined;
+ var stdout_file_stream: os.File.OutStream = undefined;
var stdout_stream = if (stdout_file) |f| x: {
- stdout_file_stream = io.FileOutStream.init(f);
+ stdout_file_stream = f.outStream();
break :x &stdout_file_stream.stream;
} else |err| err;
diff --git a/std/zig/bench.zig b/std/zig/bench.zig
index 2db33e5917..6a9e8495bd 100644
--- a/std/zig/bench.zig
+++ b/std/zig/bench.zig
@@ -24,7 +24,7 @@ pub fn main() !void {
const mb_per_sec = bytes_per_sec / (1024 * 1024);
var stdout_file = try std.io.getStdOut();
- const stdout = &std.io.FileOutStream.init(stdout_file).stream;
+ const stdout = &stdout_file.outStream().stream;
try stdout.print("{.3} MiB/s, {} KiB used \n", mb_per_sec, memory_used / 1024);
}
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index efa9ad7657..401076d53d 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1873,7 +1873,7 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined;
fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *bool) ![]u8 {
var stderr_file = try io.getStdErr();
- var stderr = &io.FileOutStream.init(stderr_file).stream;
+ var stderr = &stderr_file.outStream().stream;
var tree = try std.zig.parse(allocator, source);
defer tree.deinit();
diff --git a/test/compare_output.zig b/test/compare_output.zig
index bcd9d15b9c..554f85c168 100644
--- a/test/compare_output.zig
+++ b/test/compare_output.zig
@@ -19,7 +19,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\
\\pub fn main() void {
\\ privateFunction();
- \\ const stdout = &FileOutStream.init(getStdOut() catch unreachable).stream;
+ \\ const stdout = &(getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("OK 2\n") catch unreachable;
\\}
\\
@@ -34,7 +34,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\// purposefully conflicting function with main.zig
\\// but it's private so it should be OK
\\fn privateFunction() void {
- \\ const stdout = &FileOutStream.init(getStdOut() catch unreachable).stream;
+ \\ const stdout = &(getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("OK 1\n") catch unreachable;
\\}
\\
@@ -60,7 +60,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
tc.addSourceFile("foo.zig",
\\use @import("std").io;
\\pub fn foo_function() void {
- \\ const stdout = &FileOutStream.init(getStdOut() catch unreachable).stream;
+ \\ const stdout = &(getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("OK\n") catch unreachable;
\\}
);
@@ -71,7 +71,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\
\\pub fn bar_function() void {
\\ if (foo_function()) {
- \\ const stdout = &FileOutStream.init(getStdOut() catch unreachable).stream;
+ \\ const stdout = &(getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("OK\n") catch unreachable;
\\ }
\\}
@@ -103,7 +103,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\pub const a_text = "OK\n";
\\
\\pub fn ok() void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print(b_text) catch unreachable;
\\}
);
@@ -121,7 +121,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\const io = @import("std").io;
\\
\\pub fn main() void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a')) catch unreachable;
\\}
, "Hello, world!\n0012 012 a\n");
@@ -274,7 +274,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ var x_local : i32 = print_ok(x);
\\}
\\fn print_ok(val: @typeOf(x)) @typeOf(foo) {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("OK\n") catch unreachable;
\\ return 0;
\\}
@@ -356,7 +356,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\pub fn main() void {
\\ const bar = Bar {.field2 = 13,};
\\ const foo = Foo {.field1 = bar,};
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ if (!foo.method()) {
\\ stdout.print("BAD\n") catch unreachable;
\\ }
@@ -370,7 +370,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
cases.add("defer with only fallthrough",
\\const io = @import("std").io;
\\pub fn main() void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("before\n") catch unreachable;
\\ defer stdout.print("defer1\n") catch unreachable;
\\ defer stdout.print("defer2\n") catch unreachable;
@@ -383,7 +383,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\const io = @import("std").io;
\\const os = @import("std").os;
\\pub fn main() void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("before\n") catch unreachable;
\\ defer stdout.print("defer1\n") catch unreachable;
\\ defer stdout.print("defer2\n") catch unreachable;
@@ -400,7 +400,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ do_test() catch return;
\\}
\\fn do_test() !void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("before\n") catch unreachable;
\\ defer stdout.print("defer1\n") catch unreachable;
\\ errdefer stdout.print("deferErr\n") catch unreachable;
@@ -419,7 +419,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ do_test() catch return;
\\}
\\fn do_test() !void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print("before\n") catch unreachable;
\\ defer stdout.print("defer1\n") catch unreachable;
\\ errdefer stdout.print("deferErr\n") catch unreachable;
@@ -436,7 +436,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\const io = @import("std").io;
\\
\\pub fn main() void {
- \\ const stdout = &io.FileOutStream.init(io.getStdOut() catch unreachable).stream;
+ \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
\\ stdout.print(foo_txt) catch unreachable;
\\}
, "1234\nabcd\n");
@@ -456,7 +456,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\pub fn main() !void {
\\ var args_it = os.args();
\\ var stdout_file = try io.getStdOut();
- \\ var stdout_adapter = io.FileOutStream.init(stdout_file);
+ \\ var stdout_adapter = stdout_file.outStream();
\\ const stdout = &stdout_adapter.stream;
\\ var index: usize = 0;
\\ _ = args_it.skip();
@@ -497,7 +497,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\pub fn main() !void {
\\ var args_it = os.args();
\\ var stdout_file = try io.getStdOut();
- \\ var stdout_adapter = io.FileOutStream.init(stdout_file);
+ \\ var stdout_adapter = stdout_file.outStream();
\\ const stdout = &stdout_adapter.stream;
\\ var index: usize = 0;
\\ _ = args_it.skip();
diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig
index 36b4f8bd4f..adbc414909 100644
--- a/test/standalone/brace_expansion/main.zig
+++ b/test/standalone/brace_expansion/main.zig
@@ -191,7 +191,7 @@ pub fn main() !void {
var stdin_buf = try Buffer.initSize(global_allocator, 0);
defer stdin_buf.deinit();
- var stdin_adapter = io.FileInStream.init(stdin_file);
+ var stdin_adapter = stdin_file.inStream();
try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize));
var result_buf = try Buffer.initSize(global_allocator, 0);
diff --git a/test/tests.zig b/test/tests.zig
index 88908e8775..ec4dcd1f55 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -278,8 +278,8 @@ pub const CompareOutputContext = struct {
var stdout = Buffer.initNull(b.allocator);
var stderr = Buffer.initNull(b.allocator);
- var stdout_file_in_stream = io.FileInStream.init(child.stdout.?);
- var stderr_file_in_stream = io.FileInStream.init(child.stderr.?);
+ var stdout_file_in_stream = child.stdout.?.inStream();
+ var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable;
@@ -593,8 +593,8 @@ pub const CompileErrorContext = struct {
var stdout_buf = Buffer.initNull(b.allocator);
var stderr_buf = Buffer.initNull(b.allocator);
- var stdout_file_in_stream = io.FileInStream.init(child.stdout.?);
- var stderr_file_in_stream = io.FileInStream.init(child.stderr.?);
+ var stdout_file_in_stream = child.stdout.?.inStream();
+ var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
@@ -857,8 +857,8 @@ pub const TranslateCContext = struct {
var stdout_buf = Buffer.initNull(b.allocator);
var stderr_buf = Buffer.initNull(b.allocator);
- var stdout_file_in_stream = io.FileInStream.init(child.stdout.?);
- var stderr_file_in_stream = io.FileInStream.init(child.stderr.?);
+ var stdout_file_in_stream = child.stdout.?.inStream();
+ var stderr_file_in_stream = child.stderr.?.inStream();
stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable;
stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable;
From d1ec8377d1fcc9874c40e6603f64087f0b310677 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 1 Oct 2018 10:53:39 -0400
Subject: [PATCH 061/127] std lib: flesh out the async I/O streaming API a bit
---
src/analyze.cpp | 5 ++
std/atomic/int.zig | 4 +
std/event/fs.zig | 174 +++++++++++++++++++++++++++++-----------
std/event/io.zig | 15 ++++
std/os/file.zig | 11 +--
std/os/index.zig | 43 ++++++----
std/os/windows/util.zig | 6 ++
7 files changed, 187 insertions(+), 71 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index ae0d67b2ec..14cba3970e 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -2710,6 +2710,11 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
// be resolving ResolveStatusZeroBitsKnown
assert(field->type_entry != nullptr);
+ if (type_is_invalid(field->type_entry)) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ break;
+ }
+
if (!type_has_bits(field->type_entry))
continue;
diff --git a/std/atomic/int.zig b/std/atomic/int.zig
index 6e07ef571a..38b85873c0 100644
--- a/std/atomic/int.zig
+++ b/std/atomic/int.zig
@@ -29,5 +29,9 @@ pub fn Int(comptime T: type) type {
pub fn xchg(self: *Self, new_value: T) T {
return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
}
+
+ pub fn fetchAdd(self: *Self, op: T) T {
+ return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Add, op, AtomicOrder.SeqCst);
+ }
};
}
diff --git a/std/event/fs.zig b/std/event/fs.zig
index 7f96ae22b6..ba71677688 100644
--- a/std/event/fs.zig
+++ b/std/event/fs.zig
@@ -30,20 +30,20 @@ pub const Request = struct {
pub const PWriteV = struct {
fd: os.FileHandle,
- iov: []os.posix.iovec_const,
+ iov: []const os.posix.iovec_const,
offset: usize,
result: Error!void,
- pub const Error = os.File.WriteError;
+ pub const Error = os.PosixWriteError;
};
pub const PReadV = struct {
fd: os.FileHandle,
- iov: []os.posix.iovec,
+ iov: []const os.posix.iovec,
offset: usize,
result: Error!usize,
- pub const Error = os.File.ReadError;
+ pub const Error = os.PosixReadError;
};
pub const Open = struct {
@@ -72,28 +72,47 @@ pub const Request = struct {
};
};
+pub const PWriteVError = error{OutOfMemory} || os.File.WriteError;
+
/// data - just the inner references - must live until pwritev promise completes.
-pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {
+pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) PWriteVError!void {
+ // workaround for https://github.com/ziglang/zig/issues/1194
+ suspend {
+ resume @handle();
+ }
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
- => return await (async pwritevPosix(loop, fd, data, offset) catch unreachable),
- builtin.Os.windows => return await (async pwritevWindows(loop, fd, data, offset) catch unreachable),
+ => {
+ const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
+ defer loop.allocator.free(iovecs);
+
+ for (data) |buf, i| {
+ iovecs[i] = os.posix.iovec_const{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ };
+ }
+
+ return await (async pwritevPosix(loop, fd, iovecs, offset) catch unreachable);
+ },
+ builtin.Os.windows => {
+ const data_copy = try std.mem.dupe(loop.allocator, []const u8, data);
+ defer loop.allocator.free(data_copy);
+ return await (async pwritevWindows(loop, fd, data, offset) catch unreachable);
+ },
else => @compileError("Unsupported OS"),
}
}
-/// data - just the inner references - must live until pwritev promise completes.
-pub async fn pwritevWindows(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {
+/// data must outlive the returned promise
+pub async fn pwritevWindows(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) os.WindowsWriteError!void {
if (data.len == 0) return;
if (data.len == 1) return await (async pwriteWindows(loop, fd, data[0], offset) catch unreachable);
- const data_copy = try std.mem.dupe(loop.allocator, []const u8, data);
- defer loop.allocator.free(data_copy);
-
// TODO do these in parallel
var off = offset;
- for (data_copy) |buf| {
+ for (data) |buf| {
try await (async pwriteWindows(loop, fd, buf, off) catch unreachable);
off += buf.len;
}
@@ -144,23 +163,18 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off
}
}
-/// data - just the inner references - must live until pwritev promise completes.
-pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {
+/// iovecs must live until pwritev promise completes.
+pub async fn pwritevPosix(
+ loop: *Loop,
+ fd: os.FileHandle,
+ iovecs: []const posix.iovec_const,
+ offset: usize,
+) os.PosixWriteError!void {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
}
- const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
- defer loop.allocator.free(iovecs);
-
- for (data) |buf, i| {
- iovecs[i] = os.posix.iovec_const{
- .iov_base = buf.ptr,
- .iov_len = buf.len,
- };
- }
-
var req_node = RequestNode{
.prev = null,
.next = null,
@@ -192,38 +206,59 @@ pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const
return req_node.data.msg.PWriteV.result;
}
+pub const PReadVError = error{OutOfMemory} || os.File.ReadError;
+
/// data - just the inner references - must live until preadv promise completes.
-pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) !usize {
+pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) PReadVError!usize {
+ // workaround for https://github.com/ziglang/zig/issues/1194
+ suspend {
+ resume @handle();
+ }
+
assert(data.len != 0);
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
- => return await (async preadvPosix(loop, fd, data, offset) catch unreachable),
- builtin.Os.windows => return await (async preadvWindows(loop, fd, data, offset) catch unreachable),
+ => {
+ const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
+ defer loop.allocator.free(iovecs);
+
+ for (data) |buf, i| {
+ iovecs[i] = os.posix.iovec{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ };
+ }
+
+ return await (async preadvPosix(loop, fd, iovecs, offset) catch unreachable);
+ },
+ builtin.Os.windows => {
+ const data_copy = try std.mem.dupe(loop.allocator, []u8, data);
+ defer loop.allocator.free(data_copy);
+ return await (async preadvWindows(loop, fd, data_copy, offset) catch unreachable);
+ },
else => @compileError("Unsupported OS"),
}
}
-pub async fn preadvWindows(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: u64) !usize {
+/// data must outlive the returned promise
+pub async fn preadvWindows(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: u64) os.WindowsReadError!usize {
assert(data.len != 0);
if (data.len == 1) return await (async preadWindows(loop, fd, data[0], offset) catch unreachable);
- const data_copy = try std.mem.dupe(loop.allocator, []u8, data);
- defer loop.allocator.free(data_copy);
-
// TODO do these in parallel?
var off: usize = 0;
var iov_i: usize = 0;
var inner_off: usize = 0;
while (true) {
- const v = data_copy[iov_i];
+ const v = data[iov_i];
const amt_read = try await (async preadWindows(loop, fd, v[inner_off .. v.len - inner_off], offset + off) catch unreachable);
off += amt_read;
inner_off += amt_read;
if (inner_off == v.len) {
iov_i += 1;
inner_off = 0;
- if (iov_i == data_copy.len) {
+ if (iov_i == data.len) {
return off;
}
}
@@ -275,23 +310,18 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6
return usize(bytes_transferred);
}
-/// data - just the inner references - must live until preadv promise completes.
-pub async fn preadvPosix(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) !usize {
+/// iovecs must live until preadv promise completes
+pub async fn preadvPosix(
+ loop: *Loop,
+ fd: os.FileHandle,
+ iovecs: []const posix.iovec,
+ offset: usize,
+) os.PosixReadError!usize {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
}
- const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
- defer loop.allocator.free(iovecs);
-
- for (data) |buf, i| {
- iovecs[i] = os.posix.iovec{
- .iov_base = buf.ptr,
- .iov_len = buf.len,
- };
- }
-
var req_node = RequestNode{
.prev = null,
.next = null,
@@ -1339,3 +1369,55 @@ async fn testFsWatch(loop: *Loop) !void {
// TODO test deleting the file and then re-adding it. we should get events for both
}
+
+pub const OutStream = struct {
+ fd: os.FileHandle,
+ stream: Stream,
+ loop: *Loop,
+ offset: usize,
+
+ pub const Error = os.File.WriteError;
+ pub const Stream = event.io.OutStream(Error);
+
+ pub fn init(loop: *Loop, fd: os.FileHandle, offset: usize) OutStream {
+ return OutStream{
+ .fd = fd,
+ .loop = loop,
+ .offset = offset,
+ .stream = Stream{ .writeFn = writeFn },
+ };
+ }
+
+ async<*mem.Allocator> fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
+ const self = @fieldParentPtr(OutStream, "stream", out_stream);
+ const offset = self.offset;
+ self.offset += bytes.len;
+ return await (async pwritev(self.loop, self.fd, [][]const u8{bytes}, offset) catch unreachable);
+ }
+};
+
+pub const InStream = struct {
+ fd: os.FileHandle,
+ stream: Stream,
+ loop: *Loop,
+ offset: usize,
+
+ pub const Error = PReadVError; // TODO make this not have OutOfMemory
+ pub const Stream = event.io.InStream(Error);
+
+ pub fn init(loop: *Loop, fd: os.FileHandle, offset: usize) InStream {
+ return InStream{
+ .fd = fd,
+ .loop = loop,
+ .offset = offset,
+ .stream = Stream{ .readFn = readFn },
+ };
+ }
+
+ async<*mem.Allocator> fn readFn(in_stream: *Stream, bytes: []u8) Error!usize {
+ const self = @fieldParentPtr(InStream, "stream", in_stream);
+ const amt = try await (async preadv(self.loop, self.fd, [][]u8{bytes}, self.offset) catch unreachable);
+ self.offset += amt;
+ return amt;
+ }
+};
diff --git a/std/event/io.zig b/std/event/io.zig
index 13bff66459..6bdec54c1b 100644
--- a/std/event/io.zig
+++ b/std/event/io.zig
@@ -2,6 +2,7 @@ const std = @import("../index.zig");
const builtin = @import("builtin");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
+const mem = std.mem;
pub fn InStream(comptime ReadError: type) type {
return struct {
@@ -20,6 +21,20 @@ pub fn InStream(comptime ReadError: type) type {
return await (async self.readFn(self, buffer) catch unreachable);
}
+ pub async fn readIntLe(self: *Self, comptime T: type) !T {
+ return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
+ }
+
+ pub async fn readIntBe(self: *Self, comptime T: type) !T {
+ return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);
+ }
+
+ pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try await (async self.readFull(bytes[0..]) catch unreachable);
+ return mem.readInt(bytes, T, endian);
+ }
+
/// Same as `read` but end of stream returns `error.EndOfStream`.
pub async fn readFull(self: *Self, buf: []u8) !void {
var index: usize = 0;
diff --git a/std/os/file.zig b/std/os/file.zig
index 4a98dbcfa5..fcc626a8f2 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -365,14 +365,7 @@ pub const File = struct {
}
}
- pub const ReadError = error{
- FileClosed,
- InputOutput,
- IsDir,
- SystemResources,
-
- Unexpected,
- };
+ pub const ReadError = os.WindowsReadError || os.PosixReadError;
pub fn read(self: File, buffer: []u8) ReadError!usize {
if (is_posix) {
@@ -386,7 +379,7 @@ pub const File = struct {
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
posix.EAGAIN => unreachable,
- posix.EBADF => return error.FileClosed,
+ posix.EBADF => unreachable, // always a race condition
posix.EIO => return error.InputOutput,
posix.EISDIR => return error.IsDir,
posix.ENOBUFS => return error.SystemResources,
diff --git a/std/os/index.zig b/std/os/index.zig
index 778e3b9655..5c9e6eee82 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -72,6 +72,7 @@ pub const windowsGetQueuedCompletionStatus = windows_util.windowsGetQueuedComple
pub const WindowsWaitError = windows_util.WaitError;
pub const WindowsOpenError = windows_util.OpenError;
pub const WindowsWriteError = windows_util.WriteError;
+pub const WindowsReadError = windows_util.ReadError;
pub const FileHandle = if (is_windows) windows.HANDLE else i32;
@@ -227,6 +228,13 @@ pub fn close(handle: FileHandle) void {
}
}
+pub const PosixReadError = error{
+ InputOutput,
+ SystemResources,
+ IsDir,
+ Unexpected,
+};
+
/// Calls POSIX read, and keeps trying if it gets interrupted.
pub fn posixRead(fd: i32, buf: []u8) !void {
// Linux can return EINVAL when read amount is > 0x7ffff000
@@ -238,24 +246,27 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
const want_to_read = math.min(buf.len - index, usize(max_buf_len));
const rc = posix.read(fd, buf.ptr + index, want_to_read);
const err = posix.getErrno(rc);
- if (err > 0) {
- return switch (err) {
- posix.EINTR => continue,
- posix.EINVAL, posix.EFAULT => unreachable,
- posix.EAGAIN => unreachable,
- posix.EBADF => unreachable, // always a race condition
- posix.EIO => error.InputOutput,
- posix.EISDIR => error.IsDir,
- posix.ENOBUFS, posix.ENOMEM => error.SystemResources,
- else => unexpectedErrorPosix(err),
- };
+ switch (err) {
+ 0 => {
+ index += rc;
+ continue;
+ },
+ posix.EINTR => continue,
+ posix.EINVAL => unreachable,
+ posix.EFAULT => unreachable,
+ posix.EAGAIN => unreachable,
+ posix.EBADF => unreachable, // always a race condition
+ posix.EIO => return error.InputOutput,
+ posix.EISDIR => return error.IsDir,
+ posix.ENOBUFS => return error.SystemResources,
+ posix.ENOMEM => return error.SystemResources,
+ else => return unexpectedErrorPosix(err),
}
- index += rc;
}
}
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
-pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u64) !usize {
+pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u64) PosixReadError!usize {
switch (builtin.os) {
builtin.Os.macosx => {
// Darwin does not have preadv but it does have pread.
@@ -284,7 +295,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
posix.ESPIPE => unreachable, // fd is not seekable
- posix.EAGAIN => unreachable, // use posixAsyncPReadV for non blocking
+ posix.EAGAIN => unreachable, // this function is not for non blocking
posix.EBADF => unreachable, // always a race condition
posix.EIO => return error.InputOutput,
posix.EISDIR => return error.IsDir,
@@ -302,7 +313,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
posix.EINTR => continue,
posix.EINVAL => unreachable,
posix.EFAULT => unreachable,
- posix.EAGAIN => unreachable, // use posixAsyncPReadV for non blocking
+ posix.EAGAIN => unreachable, // don't call this function for non blocking
posix.EBADF => unreachable, // always a race condition
posix.EIO => return error.InputOutput,
posix.EISDIR => return error.IsDir,
@@ -328,7 +339,7 @@ pub const PosixWriteError = error{
};
/// Calls POSIX write, and keeps trying if it gets interrupted.
-pub fn posixWrite(fd: i32, bytes: []const u8) !void {
+pub fn posixWrite(fd: i32, bytes: []const u8) PosixWriteError!void {
// Linux can return EINVAL when write amount is > 0x7ffff000
// See https://github.com/ziglang/zig/pull/743#issuecomment-363165856
const max_bytes_len = 0x7ffff000;
diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig
index 7d983421e0..6b5628760c 100644
--- a/std/os/windows/util.zig
+++ b/std/os/windows/util.zig
@@ -42,6 +42,12 @@ pub fn windowsClose(handle: windows.HANDLE) void {
assert(windows.CloseHandle(handle) != 0);
}
+pub const ReadError = error{
+ OperationAborted,
+ BrokenPipe,
+ Unexpected,
+};
+
pub const WriteError = error{
SystemResources,
OperationAborted,
From af229c1fdc89f69273f69627ab5a0304dab11572 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 1 Oct 2018 13:43:25 -0400
Subject: [PATCH 062/127] std lib (breaking): posixRead can return less than
buffer size
closes #1414
std.io.InStream.read now can return less than buffer size
introduce std.io.InStream.readFull for previous behavior
add std.os.File.openWriteNoClobberC
rename std.os.deleteFileWindows to std.os.deleteFileW
remove std.os.deleteFilePosix
add std.os.deleteFileC
std.os.copyFile no longer takes an allocator
std.os.copyFileMode no longer takes an allocator
std.os.AtomicFile no longer takes an allocator
add std.os.renameW
add windows support for std.os.renameC
add a test for std.os.AtomicFile
---
std/build.zig | 2 +-
std/event/io.zig | 32 ++++---
std/io.zig | 40 ++++++--
std/os/child_process.zig | 10 +-
std/os/file.zig | 43 ++++-----
std/os/index.zig | 196 +++++++++++++++++++++------------------
std/os/test.zig | 21 +++++
7 files changed, 203 insertions(+), 141 deletions(-)
diff --git a/std/build.zig b/std/build.zig
index f9fed6ad2f..cc12a75df5 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -634,7 +634,7 @@ pub const Builder = struct {
warn("Unable to create path {}: {}\n", dirname, @errorName(err));
return err;
};
- os.copyFileMode(self.allocator, abs_source_path, dest_path, mode) catch |err| {
+ os.copyFileMode(abs_source_path, dest_path, mode) catch |err| {
warn("Unable to copy {} to {}: {}\n", abs_source_path, dest_path, @errorName(err));
return err;
};
diff --git a/std/event/io.zig b/std/event/io.zig
index 6bdec54c1b..fa05c61abe 100644
--- a/std/event/io.zig
+++ b/std/event/io.zig
@@ -21,6 +21,24 @@ pub fn InStream(comptime ReadError: type) type {
return await (async self.readFn(self, buffer) catch unreachable);
}
+ /// Return the number of bytes read. If it is less than buffer.len
+ /// it means end of stream.
+ pub async fn readFull(self: *Self, buffer: []u8) !usize {
+ var index: usize = 0;
+ while (index != buf.len) {
+ const amt_read = try await (async self.read(buf[index..]) catch unreachable);
+ if (amt_read == 0) return index;
+ index += amt_read;
+ }
+ return index;
+ }
+
+ /// Same as `readFull` but end of stream returns `error.EndOfStream`.
+ pub async fn readNoEof(self: *Self, buf: []u8) !void {
+ const amt_read = try await (async self.readFull(buf[index..]) catch unreachable);
+ if (amt_read < buf.len) return error.EndOfStream;
+ }
+
pub async fn readIntLe(self: *Self, comptime T: type) !T {
return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
}
@@ -31,24 +49,14 @@ pub fn InStream(comptime ReadError: type) type {
pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
- try await (async self.readFull(bytes[0..]) catch unreachable);
+ try await (async self.readNoEof(bytes[0..]) catch unreachable);
return mem.readInt(bytes, T, endian);
}
- /// Same as `read` but end of stream returns `error.EndOfStream`.
- pub async fn readFull(self: *Self, buf: []u8) !void {
- var index: usize = 0;
- while (index != buf.len) {
- const amt_read = try await (async self.read(buf[index..]) catch unreachable);
- if (amt_read == 0) return error.EndOfStream;
- index += amt_read;
- }
- }
-
pub async fn readStruct(self: *Self, comptime T: type, ptr: *T) !void {
// Only extern and packed structs have defined in-memory layout.
comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
- return await (async self.readFull(@sliceToBytes((*[1]T)(ptr)[0..])) catch unreachable);
+ return await (async self.readNoEof(@sliceToBytes((*[1]T)(ptr)[0..])) catch unreachable);
}
};
}
diff --git a/std/io.zig b/std/io.zig
index 3d20d8b9dc..c22a8ca78b 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -51,7 +51,7 @@ pub fn InStream(comptime ReadError: type) type {
var actual_buf_len: usize = 0;
while (true) {
const dest_slice = buffer.toSlice()[actual_buf_len..];
- const bytes_read = try self.readFn(self, dest_slice);
+ const bytes_read = try self.readFull(dest_slice);
actual_buf_len += bytes_read;
if (bytes_read != dest_slice.len) {
@@ -111,14 +111,27 @@ pub fn InStream(comptime ReadError: type) type {
return buf.toOwnedSlice();
}
- /// Returns the number of bytes read. If the number read is smaller than buf.len, it
- /// means the stream reached the end. Reaching the end of a stream is not an error
- /// condition.
+ /// Returns the number of bytes read. It may be less than buffer.len.
+ /// If the number of bytes read is 0, it means end of stream.
+ /// End of stream is not an error condition.
pub fn read(self: *Self, buffer: []u8) !usize {
return self.readFn(self, buffer);
}
- /// Same as `read` but end of stream returns `error.EndOfStream`.
+ /// Returns the number of bytes read. If the number read is smaller than buf.len, it
+ /// means the stream reached the end. Reaching the end of a stream is not an error
+ /// condition.
+ pub fn readFull(self: *Self, buffer: []u8) !usize {
+ var index: usize = 0;
+ while (index != buffer.len) {
+ const amt = try self.read(buffer[index..]);
+ if (amt == 0) return index;
+ index += amt;
+ }
+ return index;
+ }
+
+ /// Same as `readFull` but end of stream returns `error.EndOfStream`.
pub fn readNoEof(self: *Self, buf: []u8) !void {
const amt_read = try self.read(buf);
if (amt_read < buf.len) return error.EndOfStream;
@@ -136,6 +149,11 @@ pub fn InStream(comptime ReadError: type) type {
return @bitCast(i8, try self.readByte());
}
+ /// Reads a native-endian integer
+ pub fn readIntNe(self: *Self, comptime T: type) !T {
+ return self.readInt(builtin.endian, T);
+ }
+
pub fn readIntLe(self: *Self, comptime T: type) !T {
return self.readInt(builtin.Endian.Little, T);
}
@@ -202,6 +220,11 @@ pub fn OutStream(comptime WriteError: type) type {
}
}
+ /// Write a native-endian integer.
+ pub fn writeIntNe(self: *Self, comptime T: type, value: T) !void {
+ return self.writeInt(builtin.endian, T, value);
+ }
+
pub fn writeIntLe(self: *Self, comptime T: type, value: T) !void {
return self.writeInt(builtin.Endian.Little, T, value);
}
@@ -537,6 +560,7 @@ pub const BufferedAtomicFile = struct {
atomic_file: os.AtomicFile,
file_stream: os.File.OutStream,
buffered_stream: BufferedOutStream(os.File.WriteError),
+ allocator: *mem.Allocator,
pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
// TODO with well defined copy elision we don't need this allocation
@@ -544,10 +568,11 @@ pub const BufferedAtomicFile = struct {
.atomic_file = undefined,
.file_stream = undefined,
.buffered_stream = undefined,
+ .allocator = allocator,
});
errdefer allocator.destroy(self);
- self.atomic_file = try os.AtomicFile.init(allocator, dest_path, os.File.default_mode);
+ self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
errdefer self.atomic_file.deinit();
self.file_stream = self.atomic_file.file.outStream();
@@ -557,9 +582,8 @@ pub const BufferedAtomicFile = struct {
/// always call destroy, even after successful finish()
pub fn destroy(self: *BufferedAtomicFile) void {
- const allocator = self.atomic_file.allocator;
self.atomic_file.deinit();
- allocator.destroy(self);
+ self.allocator.destroy(self);
}
pub fn finish(self: *BufferedAtomicFile) !void {
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index 5c02f1ebe0..8bfd3f8959 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -792,13 +792,11 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
const ErrInt = @IntType(false, @sizeOf(error) * 8);
fn writeIntFd(fd: i32, value: ErrInt) !void {
- var bytes: [@sizeOf(ErrInt)]u8 = undefined;
- mem.writeInt(bytes[0..], value, builtin.endian);
- os.posixWrite(fd, bytes[0..]) catch return error.SystemResources;
+ const stream = &os.File.openHandle(fd).outStream().stream;
+ stream.writeIntNe(ErrInt, value) catch return error.SystemResources;
}
fn readIntFd(fd: i32) !ErrInt {
- var bytes: [@sizeOf(ErrInt)]u8 = undefined;
- os.posixRead(fd, bytes[0..]) catch return error.SystemResources;
- return mem.readInt(bytes[0..], ErrInt, builtin.endian);
+ const stream = &os.File.openHandle(fd).inStream().stream;
+ return stream.readIntNe(ErrInt) catch return error.SystemResources;
}
diff --git a/std/os/file.zig b/std/os/file.zig
index fcc626a8f2..f5e754cdc7 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -103,9 +103,8 @@ pub const File = struct {
/// Call close to clean up.
pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
if (is_posix) {
- const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_EXCL;
- const fd = try os.posixOpen(path, flags, file_mode);
- return openHandle(fd);
+ const path_c = try os.toPosixPath(path);
+ return openWriteNoClobberC(path_c, file_mode);
} else if (is_windows) {
const path_w = try windows_util.sliceToPrefixedFileW(path);
return openWriteNoClobberW(&path_w, file_mode);
@@ -114,6 +113,19 @@ pub const File = struct {
}
}
+ pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File {
+ if (is_posix) {
+ const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_EXCL;
+ const fd = try os.posixOpenC(path, flags, file_mode);
+ return openHandle(fd);
+ } else if (is_windows) {
+ const path_w = try windows_util.cStrToPrefixedFileW(path);
+ return openWriteNoClobberW(&path_w, file_mode);
+ } else {
+ @compileError("TODO implement openWriteMode for this OS");
+ }
+ }
+
pub fn openWriteNoClobberW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
const handle = try os.windowsOpenW(
path_w,
@@ -369,28 +381,7 @@ pub const File = struct {
pub fn read(self: File, buffer: []u8) ReadError!usize {
if (is_posix) {
- var index: usize = 0;
- while (index < buffer.len) {
- const amt_read = posix.read(self.handle, buffer.ptr + index, buffer.len - index);
- const read_err = posix.getErrno(amt_read);
- if (read_err > 0) {
- switch (read_err) {
- posix.EINTR => continue,
- posix.EINVAL => unreachable,
- posix.EFAULT => unreachable,
- posix.EAGAIN => unreachable,
- posix.EBADF => unreachable, // always a race condition
- posix.EIO => return error.InputOutput,
- posix.EISDIR => return error.IsDir,
- posix.ENOBUFS => return error.SystemResources,
- posix.ENOMEM => return error.SystemResources,
- else => return os.unexpectedErrorPosix(read_err),
- }
- }
- if (amt_read == 0) return index;
- index += amt_read;
- }
- return index;
+ return os.posixRead(self.handle, buffer);
} else if (is_windows) {
var index: usize = 0;
while (index < buffer.len) {
@@ -409,7 +400,7 @@ pub const File = struct {
}
return index;
} else {
- unreachable;
+ @compileError("Unsupported OS");
}
}
diff --git a/std/os/index.zig b/std/os/index.zig
index 5c9e6eee82..40219b9cfa 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -104,30 +104,17 @@ pub fn getRandomBytes(buf: []u8) !void {
Os.linux => while (true) {
// TODO check libc version and potentially call c.getrandom.
// See #397
- const err = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
- if (err > 0) {
- switch (err) {
- posix.EINVAL => unreachable,
- posix.EFAULT => unreachable,
- posix.EINTR => continue,
- posix.ENOSYS => {
- const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0);
- defer close(fd);
-
- try posixRead(fd, buf);
- return;
- },
- else => return unexpectedErrorPosix(err),
- }
+ const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
+ switch (errno) {
+ 0 => return,
+ posix.EINVAL => unreachable,
+ posix.EFAULT => unreachable,
+ posix.EINTR => continue,
+ posix.ENOSYS => return getRandomBytesDevURandom(buf),
+ else => return unexpectedErrorPosix(errno),
}
- return;
- },
- Os.macosx, Os.ios => {
- const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0);
- defer close(fd);
-
- try posixRead(fd, buf);
},
+ Os.macosx, Os.ios => return getRandomBytesDevURandom(buf),
Os.windows => {
// Call RtlGenRandom() instead of CryptGetRandom() on Windows
// https://github.com/rust-lang-nursery/rand/issues/111
@@ -151,6 +138,22 @@ pub fn getRandomBytes(buf: []u8) !void {
}
}
+fn getRandomBytesDevURandom(buf: []u8) !void {
+ const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0);
+ defer close(fd);
+
+ const stream = &File.openHandle(fd).inStream().stream;
+ stream.readNoEof(buf) catch |err| switch (err) {
+ error.EndOfStream => unreachable,
+ error.OperationAborted => unreachable,
+ error.BrokenPipe => unreachable,
+ error.Unexpected => return error.Unexpected,
+ error.InputOutput => return error.Unexpected,
+ error.SystemResources => return error.Unexpected,
+ error.IsDir => unreachable,
+ };
+}
+
test "os.getRandomBytes" {
var buf_a: [50]u8 = undefined;
var buf_b: [50]u8 = undefined;
@@ -235,8 +238,9 @@ pub const PosixReadError = error{
Unexpected,
};
-/// Calls POSIX read, and keeps trying if it gets interrupted.
-pub fn posixRead(fd: i32, buf: []u8) !void {
+/// Returns the number of bytes that were read, which can be less than
+/// buf.len. If 0 bytes were read, that means EOF.
+pub fn posixRead(fd: i32, buf: []u8) PosixReadError!usize {
// Linux can return EINVAL when read amount is > 0x7ffff000
// See https://github.com/ziglang/zig/pull/743#issuecomment-363158274
const max_buf_len = 0x7ffff000;
@@ -249,7 +253,9 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
switch (err) {
0 => {
index += rc;
- continue;
+ if (rc == want_to_read) continue;
+ // Read returned less than buf.len.
+ return index;
},
posix.EINTR => continue,
posix.EINVAL => unreachable,
@@ -263,6 +269,7 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
else => return unexpectedErrorPosix(err),
}
}
+ return index;
}
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
@@ -962,16 +969,16 @@ pub const DeleteFileError = error{
pub fn deleteFile(file_path: []const u8) DeleteFileError!void {
if (builtin.os == Os.windows) {
- return deleteFileWindows(file_path);
+ const file_path_w = try windows_util.sliceToPrefixedFileW(file_path);
+ return deleteFileW(&file_path_w);
} else {
- return deleteFilePosix(file_path);
+ const file_path_c = try toPosixPath(file_path);
+ return deleteFileC(&file_path_c);
}
}
-pub fn deleteFileWindows(file_path: []const u8) !void {
- const file_path_w = try windows_util.sliceToPrefixedFileW(file_path);
-
- if (windows.DeleteFileW(&file_path_w) == 0) {
+pub fn deleteFileW(file_path: [*]const u16) DeleteFileError!void {
+ if (windows.DeleteFileW(file_path) == 0) {
const err = windows.GetLastError();
switch (err) {
windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
@@ -983,50 +990,49 @@ pub fn deleteFileWindows(file_path: []const u8) !void {
}
}
-pub fn deleteFilePosixC(file_path: [*]const u8) !void {
- const err = posix.getErrno(posix.unlink(file_path));
- switch (err) {
- 0 => return,
- posix.EACCES => return error.AccessDenied,
- posix.EPERM => return error.AccessDenied,
- posix.EBUSY => return error.FileBusy,
- posix.EFAULT => unreachable,
- posix.EINVAL => unreachable,
- posix.EIO => return error.FileSystem,
- posix.EISDIR => return error.IsDir,
- posix.ELOOP => return error.SymLinkLoop,
- posix.ENAMETOOLONG => return error.NameTooLong,
- posix.ENOENT => return error.FileNotFound,
- posix.ENOTDIR => return error.NotDir,
- posix.ENOMEM => return error.SystemResources,
- posix.EROFS => return error.ReadOnlyFileSystem,
- else => return unexpectedErrorPosix(err),
+pub fn deleteFileC(file_path: [*]const u8) DeleteFileError!void {
+ if (is_windows) {
+ const file_path_w = try windows_util.cStrToPrefixedFileW(file_path);
+ return deleteFileW(&file_path_w);
+ } else {
+ const err = posix.getErrno(posix.unlink(file_path));
+ switch (err) {
+ 0 => return,
+ posix.EACCES => return error.AccessDenied,
+ posix.EPERM => return error.AccessDenied,
+ posix.EBUSY => return error.FileBusy,
+ posix.EFAULT => unreachable,
+ posix.EINVAL => unreachable,
+ posix.EIO => return error.FileSystem,
+ posix.EISDIR => return error.IsDir,
+ posix.ELOOP => return error.SymLinkLoop,
+ posix.ENAMETOOLONG => return error.NameTooLong,
+ posix.ENOENT => return error.FileNotFound,
+ posix.ENOTDIR => return error.NotDir,
+ posix.ENOMEM => return error.SystemResources,
+ posix.EROFS => return error.ReadOnlyFileSystem,
+ else => return unexpectedErrorPosix(err),
+ }
}
}
-pub fn deleteFilePosix(file_path: []const u8) !void {
- const file_path_c = try toPosixPath(file_path);
- return deleteFilePosixC(&file_path_c);
-}
-
/// Guaranteed to be atomic. However until https://patchwork.kernel.org/patch/9636735/ is
/// merged and readily available,
/// there is a possibility of power loss or application termination leaving temporary files present
/// in the same directory as dest_path.
/// Destination file will have the same mode as the source file.
-/// TODO investigate if this can work with no allocator
-pub fn copyFile(allocator: *Allocator, source_path: []const u8, dest_path: []const u8) !void {
+pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
var in_file = try os.File.openRead(source_path);
defer in_file.close();
const mode = try in_file.mode();
- var atomic_file = try AtomicFile.init(allocator, dest_path, mode);
+ var atomic_file = try AtomicFile.init(dest_path, mode);
defer atomic_file.deinit();
var buf: [page_size]u8 = undefined;
while (true) {
- const amt = try in_file.read(buf[0..]);
+ const amt = try in_file.readFull(buf[0..]);
try atomic_file.file.write(buf[0..amt]);
if (amt != buf.len) {
return atomic_file.finish();
@@ -1037,12 +1043,11 @@ pub fn copyFile(allocator: *Allocator, source_path: []const u8, dest_path: []con
/// Guaranteed to be atomic. However until https://patchwork.kernel.org/patch/9636735/ is
/// merged and readily available,
/// there is a possibility of power loss or application termination leaving temporary files present
-/// TODO investigate if this can work with no allocator
-pub fn copyFileMode(allocator: *Allocator, source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
+pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
var in_file = try os.File.openRead(source_path);
defer in_file.close();
- var atomic_file = try AtomicFile.init(allocator, dest_path, mode);
+ var atomic_file = try AtomicFile.init(dest_path, mode);
defer atomic_file.deinit();
var buf: [page_size]u8 = undefined;
@@ -1056,35 +1061,38 @@ pub fn copyFileMode(allocator: *Allocator, source_path: []const u8, dest_path: [
}
pub const AtomicFile = struct {
- /// TODO investigate if we can make this work with no allocator
- allocator: *Allocator,
file: os.File,
- tmp_path: []u8,
+ tmp_path_buf: [MAX_PATH_BYTES]u8,
dest_path: []const u8,
finished: bool,
+ const InitError = os.File.OpenError;
+
/// dest_path must remain valid for the lifetime of AtomicFile
/// call finish to atomically replace dest_path with contents
- pub fn init(allocator: *Allocator, dest_path: []const u8, mode: File.Mode) !AtomicFile {
+ /// TODO once we have null terminated pointers, use the
+ /// openWriteNoClobberN function
+ pub fn init(dest_path: []const u8, mode: File.Mode) InitError!AtomicFile {
const dirname = os.path.dirname(dest_path);
-
var rand_buf: [12]u8 = undefined;
-
const dirname_component_len = if (dirname) |d| d.len + 1 else 0;
- const tmp_path = try allocator.alloc(u8, dirname_component_len +
- base64.Base64Encoder.calcSize(rand_buf.len));
- errdefer allocator.free(tmp_path);
+ const encoded_rand_len = comptime base64.Base64Encoder.calcSize(rand_buf.len);
+ const tmp_path_len = dirname_component_len + encoded_rand_len;
+ var tmp_path_buf: [MAX_PATH_BYTES]u8 = undefined;
+ if (tmp_path_len >= tmp_path_buf.len) return error.NameTooLong;
if (dirname) |dir| {
- mem.copy(u8, tmp_path[0..], dir);
- tmp_path[dir.len] = os.path.sep;
+ mem.copy(u8, tmp_path_buf[0..], dir);
+ tmp_path_buf[dir.len] = os.path.sep;
}
+ tmp_path_buf[tmp_path_len] = 0;
+
while (true) {
try getRandomBytes(rand_buf[0..]);
- b64_fs_encoder.encode(tmp_path[dirname_component_len..], rand_buf);
+ b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
- const file = os.File.openWriteNoClobber(tmp_path, mode) catch |err| switch (err) {
+ const file = os.File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
error.PathAlreadyExists => continue,
// TODO zig should figure out that this error set does not include PathAlreadyExists since
// it is handled in the above switch
@@ -1092,9 +1100,8 @@ pub const AtomicFile = struct {
};
return AtomicFile{
- .allocator = allocator,
.file = file,
- .tmp_path = tmp_path,
+ .tmp_path_buf = tmp_path_buf,
.dest_path = dest_path,
.finished = false,
};
@@ -1105,8 +1112,7 @@ pub const AtomicFile = struct {
pub fn deinit(self: *AtomicFile) void {
if (!self.finished) {
self.file.close();
- deleteFile(self.tmp_path) catch {};
- self.allocator.free(self.tmp_path);
+ deleteFileC(&self.tmp_path_buf) catch {};
self.finished = true;
}
}
@@ -1114,15 +1120,25 @@ pub const AtomicFile = struct {
pub fn finish(self: *AtomicFile) !void {
assert(!self.finished);
self.file.close();
- try rename(self.tmp_path, self.dest_path);
- self.allocator.free(self.tmp_path);
self.finished = true;
+ if (is_posix) {
+ const dest_path_c = try toPosixPath(self.dest_path);
+ return renameC(&self.tmp_path_buf, &dest_path_c);
+ } else if (is_windows) {
+ const dest_path_w = try windows_util.sliceToPrefixedFileW(self.dest_path);
+ const tmp_path_w = try windows_util.cStrToPrefixedFileW(&self.tmp_path_buf);
+ return renameW(&tmp_path_w, &dest_path_w);
+ } else {
+ @compileError("Unsupported OS");
+ }
}
};
pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) !void {
if (is_windows) {
- @compileError("TODO implement for windows");
+ const old_path_w = try windows_util.cStrToPrefixedFileW(old_path);
+ const new_path_w = try windows_util.cStrToPrefixedFileW(new_path);
+ return renameW(&old_path_w, &new_path_w);
} else {
const err = posix.getErrno(posix.rename(old_path, new_path));
switch (err) {
@@ -1150,17 +1166,21 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) !void {
}
}
+pub fn renameW(old_path: [*]const u16, new_path: [*]const u16) !void {
+ const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
+ if (windows.MoveFileExW(old_path, new_path, flags) == 0) {
+ const err = windows.GetLastError();
+ switch (err) {
+ else => return unexpectedErrorWindows(err),
+ }
+ }
+}
+
pub fn rename(old_path: []const u8, new_path: []const u8) !void {
if (is_windows) {
- const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
const old_path_w = try windows_util.sliceToPrefixedFileW(old_path);
const new_path_w = try windows_util.sliceToPrefixedFileW(new_path);
- if (windows.MoveFileExW(&old_path_w, &new_path_w, flags) == 0) {
- const err = windows.GetLastError();
- switch (err) {
- else => return unexpectedErrorWindows(err),
- }
- }
+ return renameW(&old_path_w, &new_path_w);
} else {
const old_path_c = try toPosixPath(old_path);
const new_path_c = try toPosixPath(new_path);
diff --git a/std/os/test.zig b/std/os/test.zig
index 653ab13fd8..5142920687 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -2,6 +2,7 @@ const std = @import("../index.zig");
const os = std.os;
const assert = std.debug.assert;
const io = std.io;
+const mem = std.mem;
const a = std.debug.global_allocator;
@@ -80,3 +81,23 @@ test "cpu count" {
const cpu_count = try std.os.cpuCount(a);
assert(cpu_count >= 1);
}
+
+test "AtomicFile" {
+ var buffer: [1024]u8 = undefined;
+ const allocator = &std.heap.FixedBufferAllocator.init(buffer[0..]).allocator;
+ const test_out_file = "tmp_atomic_file_test_dest.txt";
+ const test_content =
+ \\ hello!
+ \\ this is a test file
+ ;
+ {
+ var af = try os.AtomicFile.init(test_out_file, os.File.default_mode);
+ defer af.deinit();
+ try af.file.write(test_content);
+ try af.finish();
+ }
+ const content = try io.readFileAlloc(allocator, test_out_file);
+ assert(mem.eql(u8, content, test_content));
+
+ try os.deleteFile(test_out_file);
+}
From d4d22df1d90d9d78f2960e807c3dad061ed1c71a Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 1 Oct 2018 14:10:18 -0400
Subject: [PATCH 063/127] increase stack size on windows for all executables
fixes test failures
See #157
---
src/link.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/link.cpp b/src/link.cpp
index a280c31f74..2b58f14266 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -434,6 +434,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append("-DEBUG");
}
+ if (g->out_type == OutTypeExe) {
+ // TODO compile time stack upper bound detection
+ lj->args.append("/STACK:16777216");
+ }
+
coff_append_machine_arg(g, &lj->args);
if (g->windows_subsystem_windows) {
From bc3e99c5e5a5f054e57a7056a64ff08762d42e9f Mon Sep 17 00:00:00 2001
From: Jimmi Holst Christensen
Date: Mon, 1 Oct 2018 20:30:34 +0200
Subject: [PATCH 064/127] Fixed StackTrace not being resolved when panic is
invalid (#1615)
---
src/analyze.cpp | 4 +++-
test/compile_errors.zig | 10 ++++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 14cba3970e..4f8b2f8880 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1058,7 +1058,10 @@ ZigType *get_ptr_to_stack_trace_type(CodeGen *g) {
if (g->stack_trace_type == nullptr) {
ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");
assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);
+
g->stack_trace_type = stack_trace_type_val->data.x_type;
+ assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));
+
g->ptr_to_stack_trace_type = get_pointer_to_type(g, g->stack_trace_type, false);
}
return g->ptr_to_stack_trace_type;
@@ -6560,4 +6563,3 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f
LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
return LLVMStoreSizeOfType(g->target_data_ref, field_type);
}
-
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index fb7b536be9..3b1b4a2496 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,16 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "Panic declared with wrong type signature in tests",
+ \\test "" {}
+ \\
+ \\pub fn panic() void {}
+ \\
+ ,
+ ".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'",
+ );
+
cases.add(
"compile error when evaluating return type of inferred error set",
\\const Car = struct {
From cd211bcc20d3d1ddd1a50d57c7645aa3445934f0 Mon Sep 17 00:00:00 2001
From: Wink Saville
Date: Mon, 1 Oct 2018 21:51:53 -0700
Subject: [PATCH 065/127] Add doc comment for tokenLocationPtr (#1618)
The algorithm seemed unusual and I had spent some effort understanding
it, so I thought I'd add a comment.
---
std/zig/ast.zig | 1 +
1 file changed, 1 insertion(+)
diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index 2102da456c..e2ac5f6341 100644
--- a/std/zig/ast.zig
+++ b/std/zig/ast.zig
@@ -45,6 +45,7 @@ pub const Tree = struct {
line_end: usize,
};
+ /// Return the Location of the token relative to the offset specified by `start_index`.
pub fn tokenLocationPtr(self: *Tree, start_index: usize, token: *const Token) Location {
var loc = Location{
.line = 0,
From 24bbade217ed814bd6c4d94ed93442824b7153a4 Mon Sep 17 00:00:00 2001
From: Ben Noordhuis
Date: Tue, 2 Oct 2018 12:31:21 +0200
Subject: [PATCH 066/127] fix build-exe for --target-arch wasm32 (#1570)
Pass --no-entry instead of --relocatable to lld. Both stop a reference
to the _start() entry point from being emitted but --relocatable also
prevents public symbols from being exported when creating an executable.
---
src/link.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/link.cpp b/src/link.cpp
index 2b58f14266..e3753bff24 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -386,7 +386,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
static void construct_linker_job_wasm(LinkJob *lj) {
CodeGen *g = lj->codegen;
- lj->args.append("--relocatable"); // So lld doesn't look for _start.
+ lj->args.append("--no-entry"); // So lld doesn't look for _start.
lj->args.append("-o");
lj->args.append(buf_ptr(&g->output_file_path));
From acefcdbca58efd97bf5346eb7dae22c49efa1a3d Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 2 Oct 2018 14:08:32 -0400
Subject: [PATCH 067/127] add std.os.linux.vfork and std.os.linux.exit_group
---
std/os/index.zig | 29 ++++++++++++++++++-----------
std/os/linux/index.zig | 14 ++++++++++++++
2 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/std/os/index.zig b/std/os/index.zig
index 40219b9cfa..b1356f8ed7 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -634,18 +634,25 @@ pub const PosixExecveError = error{
fn posixExecveErrnoToErr(err: usize) PosixExecveError {
assert(err > 0);
- return switch (err) {
+ switch (err) {
posix.EFAULT => unreachable,
- posix.E2BIG, posix.EMFILE, posix.ENAMETOOLONG, posix.ENFILE, posix.ENOMEM => error.SystemResources,
- posix.EACCES, posix.EPERM => error.AccessDenied,
- posix.EINVAL, posix.ENOEXEC => error.InvalidExe,
- posix.EIO, posix.ELOOP => error.FileSystem,
- posix.EISDIR => error.IsDir,
- posix.ENOENT => error.FileNotFound,
- posix.ENOTDIR => error.NotDir,
- posix.ETXTBSY => error.FileBusy,
- else => unexpectedErrorPosix(err),
- };
+ posix.E2BIG => return error.SystemResources,
+ posix.EMFILE => return error.SystemResources,
+ posix.ENAMETOOLONG => return error.SystemResources,
+ posix.ENFILE => return error.SystemResources,
+ posix.ENOMEM => return error.SystemResources,
+ posix.EACCES => return error.AccessDenied,
+ posix.EPERM => return error.AccessDenied,
+ posix.EINVAL => return error.InvalidExe,
+ posix.ENOEXEC => return error.InvalidExe,
+ posix.EIO => return error.FileSystem,
+ posix.ELOOP => return error.FileSystem,
+ posix.EISDIR => return error.IsDir,
+ posix.ENOENT => return error.FileNotFound,
+ posix.ENOTDIR => return error.NotDir,
+ posix.ETXTBSY => return error.FileBusy,
+ else => return unexpectedErrorPosix(err),
+ }
}
pub var linux_aux_raw = []usize{0} ** 38;
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index e00c664afa..8819aa21cd 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -719,6 +719,15 @@ pub fn fork() usize {
return syscall0(SYS_fork);
}
+/// This must be inline, and inline call the syscall function, because if the
+/// child does a return it will clobber the parent's stack.
+/// It is advised to avoid this function and use clone instead, because
+/// the compiler is not aware of how vfork affects control flow and you may
+/// see different results in optimized builds.
+pub inline fn vfork() usize {
+ return @inlineCall(syscall0, SYS_vfork);
+}
+
pub fn futex_wait(uaddr: usize, futex_op: u32, val: i32, timeout: ?*timespec) usize {
return syscall4(SYS_futex, uaddr, futex_op, @bitCast(u32, val), @ptrToInt(timeout));
}
@@ -883,6 +892,11 @@ pub fn exit(status: i32) noreturn {
unreachable;
}
+pub fn exit_group(status: i32) noreturn {
+ _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status)));
+ unreachable;
+}
+
pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
return syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags));
}
From 66cb75d1148fffdd161e7829b9e27aa52f0f1616 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 3 Oct 2018 13:19:10 -0400
Subject: [PATCH 068/127] std.Mutex: implement blocking mutexes on linux
closes #1463
Thanks to Shawn Landden for the original pull request.
This commit is based on that code.
---
CMakeLists.txt | 1 +
std/event/loop.zig | 14 +++++-----
std/index.zig | 16 +++++++-----
std/mutex.zig | 59 ++++++++++++++++++++++++++++++++++++++----
std/os/index.zig | 2 +-
std/os/linux/index.zig | 8 +++---
std/spinlock.zig | 32 +++++++++++++++++++++++
7 files changed, 107 insertions(+), 25 deletions(-)
create mode 100644 std/spinlock.zig
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 25c0dfa126..c1ea43943d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -635,6 +635,7 @@ set(ZIG_STD_FILES
"special/init-lib/src/main.zig"
"special/panic.zig"
"special/test_runner.zig"
+ "spinlock.zig"
"unicode.zig"
"zig/ast.zig"
"zig/index.zig"
diff --git a/std/event/loop.zig b/std/event/loop.zig
index e87e928049..aeb0f6377b 100644
--- a/std/event/loop.zig
+++ b/std/event/loop.zig
@@ -736,8 +736,8 @@ pub const Loop = struct {
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
},
builtin.Os.linux => {
- _ = @atomicRmw(u8, &self.os_data.fs_queue_item, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
- const rc = os.linux.futex_wake(@ptrToInt(&self.os_data.fs_queue_item), os.linux.FUTEX_WAKE, 1);
+ _ = @atomicRmw(i32, &self.os_data.fs_queue_item, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
+ const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);
switch (os.linux.getErrno(rc)) {
0 => {},
posix.EINVAL => unreachable,
@@ -757,7 +757,7 @@ pub const Loop = struct {
fn posixFsRun(self: *Loop) void {
while (true) {
if (builtin.os == builtin.Os.linux) {
- _ = @atomicRmw(u8, &self.os_data.fs_queue_item, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst);
+ _ = @atomicRmw(i32, &self.os_data.fs_queue_item, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst);
}
while (self.os_data.fs_queue.get()) |node| {
switch (node.data.msg) {
@@ -794,11 +794,9 @@ pub const Loop = struct {
}
switch (builtin.os) {
builtin.Os.linux => {
- const rc = os.linux.futex_wait(@ptrToInt(&self.os_data.fs_queue_item), os.linux.FUTEX_WAIT, 0, null);
+ const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);
switch (os.linux.getErrno(rc)) {
- 0 => continue,
- posix.EINTR => continue,
- posix.EAGAIN => continue,
+ 0, posix.EINTR, posix.EAGAIN => continue,
else => unreachable,
}
},
@@ -838,7 +836,7 @@ pub const Loop = struct {
final_eventfd: i32,
final_eventfd_event: os.linux.epoll_event,
fs_thread: *os.Thread,
- fs_queue_item: u8,
+ fs_queue_item: i32,
fs_queue: std.atomic.Queue(fs.Request),
fs_end_request: fs.RequestNode,
};
diff --git a/std/index.zig b/std/index.zig
index ec627c9fc6..18489969df 100644
--- a/std/index.zig
+++ b/std/index.zig
@@ -1,15 +1,16 @@
-pub const ArrayList = @import("array_list.zig").ArrayList;
pub const AlignedArrayList = @import("array_list.zig").AlignedArrayList;
+pub const ArrayList = @import("array_list.zig").ArrayList;
+pub const AutoHashMap = @import("hash_map.zig").AutoHashMap;
pub const BufMap = @import("buf_map.zig").BufMap;
pub const BufSet = @import("buf_set.zig").BufSet;
pub const Buffer = @import("buffer.zig").Buffer;
pub const BufferOutStream = @import("io.zig").BufferOutStream;
-pub const HashMap = @import("hash_map.zig").HashMap;
-pub const AutoHashMap = @import("hash_map.zig").AutoHashMap;
-pub const LinkedList = @import("linked_list.zig").LinkedList;
-pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
pub const DynLib = @import("dynamic_library.zig").DynLib;
+pub const HashMap = @import("hash_map.zig").HashMap;
+pub const LinkedList = @import("linked_list.zig").LinkedList;
pub const Mutex = @import("mutex.zig").Mutex;
+pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
+pub const SpinLock = @import("spinlock.zig").SpinLock;
pub const atomic = @import("atomic/index.zig");
pub const base64 = @import("base64.zig");
@@ -45,15 +46,16 @@ pub const lazyInit = @import("lazy_init.zig").lazyInit;
test "std" {
// run tests from these
- _ = @import("atomic/index.zig");
_ = @import("array_list.zig");
+ _ = @import("atomic/index.zig");
_ = @import("buf_map.zig");
_ = @import("buf_set.zig");
_ = @import("buffer.zig");
_ = @import("hash_map.zig");
_ = @import("linked_list.zig");
- _ = @import("segmented_list.zig");
_ = @import("mutex.zig");
+ _ = @import("segmented_list.zig");
+ _ = @import("spinlock.zig");
_ = @import("base64.zig");
_ = @import("build.zig");
diff --git a/std/mutex.zig b/std/mutex.zig
index 6aee87d1d7..9dc0c23d6d 100644
--- a/std/mutex.zig
+++ b/std/mutex.zig
@@ -3,25 +3,74 @@ const builtin = @import("builtin");
const AtomicOrder = builtin.AtomicOrder;
const AtomicRmwOp = builtin.AtomicRmwOp;
const assert = std.debug.assert;
+const SpinLock = std.SpinLock;
+const linux = std.os.linux;
-/// TODO use syscalls instead of a spinlock
+/// Lock may be held only once. If the same thread
+/// tries to acquire the same mutex twice, it deadlocks.
pub const Mutex = struct {
- lock: u8, // TODO use a bool
+ /// 0: unlocked
+ /// 1: locked, no waiters
+ /// 2: locked, one or more waiters
+ linux_lock: @typeOf(linux_lock_init),
+
+ /// TODO better implementation than spin lock
+ spin_lock: @typeOf(spin_lock_init),
+
+ const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {};
+ const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {};
pub const Held = struct {
mutex: *Mutex,
pub fn release(self: Held) void {
- assert(@atomicRmw(u8, &self.mutex.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+ if (builtin.os == builtin.Os.linux) {
+ // Always unlock. If the previous state was Locked-No-Waiters, then we're done.
+ // Otherwise, wake a waiter up.
+ const prev = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
+ if (prev != 1) {
+ assert(prev == 2);
+ const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE, 1);
+ switch (linux.getErrno(rc)) {
+ 0 => {},
+ linux.EINVAL => unreachable,
+ else => unreachable,
+ }
+ }
+ } else {
+ SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock });
+ }
}
};
pub fn init() Mutex {
- return Mutex{ .lock = 0 };
+ return Mutex{
+ .linux_lock = linux_lock_init,
+ .spin_lock = spin_lock_init,
+ };
}
pub fn acquire(self: *Mutex) Held {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
+ if (builtin.os == builtin.Os.linux) {
+ // First try to go from Unlocked to Locked-No-Waiters. If this succeeds, no syscalls are needed.
+ // Otherwise, we need to be in the Locked-With-Waiters state. If we are already in that state,
+ // proceed to futex_wait. Otherwise, try to go from Locked-No-Waiters to Locked-With-Waiters.
+ // If that succeeds, proceed to futex_wait. Otherwise start the whole loop over again.
+ while (@cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic)) |l| {
+ if (l == 2 or
+ @cmpxchgWeak(i32, &self.linux_lock, 1, 2, AtomicOrder.Acquire, AtomicOrder.Monotonic) == null)
+ {
+ const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT, 2, null);
+ switch (linux.getErrno(rc)) {
+ 0, linux.EINTR, linux.EAGAIN => continue,
+ linux.EINVAL => unreachable,
+ else => unreachable,
+ }
+ }
+ }
+ } else {
+ _ = self.spin_lock.acquire();
+ }
return Held{ .mutex = self };
}
};
diff --git a/std/os/index.zig b/std/os/index.zig
index b1356f8ed7..aee375405b 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -2839,7 +2839,7 @@ pub const Thread = struct {
while (true) {
const pid_value = @atomicLoad(i32, &self.data.handle, builtin.AtomicOrder.SeqCst);
if (pid_value == 0) break;
- const rc = linux.futex_wait(@ptrToInt(&self.data.handle), linux.FUTEX_WAIT, pid_value, null);
+ const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null);
switch (linux.getErrno(rc)) {
0 => continue,
posix.EINTR => continue,
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index 8819aa21cd..af61aeb886 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -728,12 +728,12 @@ pub inline fn vfork() usize {
return @inlineCall(syscall0, SYS_vfork);
}
-pub fn futex_wait(uaddr: usize, futex_op: u32, val: i32, timeout: ?*timespec) usize {
- return syscall4(SYS_futex, uaddr, futex_op, @bitCast(u32, val), @ptrToInt(timeout));
+pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize {
+ return syscall4(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout));
}
-pub fn futex_wake(uaddr: usize, futex_op: u32, val: i32) usize {
- return syscall3(SYS_futex, uaddr, futex_op, @bitCast(u32, val));
+pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize {
+ return syscall3(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val));
}
pub fn getcwd(buf: [*]u8, size: usize) usize {
diff --git a/std/spinlock.zig b/std/spinlock.zig
new file mode 100644
index 0000000000..75fdf9f6e1
--- /dev/null
+++ b/std/spinlock.zig
@@ -0,0 +1,32 @@
+const std = @import("index.zig");
+const builtin = @import("builtin");
+const AtomicOrder = builtin.AtomicOrder;
+const AtomicRmwOp = builtin.AtomicRmwOp;
+const assert = std.debug.assert;
+
+pub const SpinLock = struct {
+ lock: u8, // TODO use a bool or enum
+
+ pub const Held = struct {
+ spinlock: *SpinLock,
+
+ pub fn release(self: Held) void {
+ assert(@atomicRmw(u8, &self.spinlock.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+ }
+ };
+
+ pub fn init() SpinLock {
+ return SpinLock{ .lock = 0 };
+ }
+
+ pub fn acquire(self: *SpinLock) Held {
+ while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
+ return Held{ .spinlock = self };
+ }
+};
+
+test "spinlock" {
+ var lock = SpinLock.init();
+ const held = lock.acquire();
+ defer held.release();
+}
From 3f13a59cbc4235a5abcc2ca35bbc3f172336fd61 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 3 Oct 2018 14:55:12 -0400
Subject: [PATCH 069/127] better mutex implementation
based on Ulrich Drepper's "Futexes are tricky" paper, Mutex, Take 3
also includes tests
---
std/mutex.zig | 81 ++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 61 insertions(+), 20 deletions(-)
diff --git a/std/mutex.zig b/std/mutex.zig
index 9dc0c23d6d..e35bd81bc4 100644
--- a/std/mutex.zig
+++ b/std/mutex.zig
@@ -8,6 +8,8 @@ const linux = std.os.linux;
/// Lock may be held only once. If the same thread
/// tries to acquire the same mutex twice, it deadlocks.
+/// The Linux implementation is based on mutex3 from
+/// https://www.akkadia.org/drepper/futex.pdf
pub const Mutex = struct {
/// 0: unlocked
/// 1: locked, no waiters
@@ -25,12 +27,10 @@ pub const Mutex = struct {
pub fn release(self: Held) void {
if (builtin.os == builtin.Os.linux) {
- // Always unlock. If the previous state was Locked-No-Waiters, then we're done.
- // Otherwise, wake a waiter up.
- const prev = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
- if (prev != 1) {
- assert(prev == 2);
- const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE, 1);
+ const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
+ if (c != 1) {
+ _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
+ const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
switch (linux.getErrno(rc)) {
0 => {},
linux.EINVAL => unreachable,
@@ -52,21 +52,18 @@ pub const Mutex = struct {
pub fn acquire(self: *Mutex) Held {
if (builtin.os == builtin.Os.linux) {
- // First try to go from Unlocked to Locked-No-Waiters. If this succeeds, no syscalls are needed.
- // Otherwise, we need to be in the Locked-With-Waiters state. If we are already in that state,
- // proceed to futex_wait. Otherwise, try to go from Locked-No-Waiters to Locked-With-Waiters.
- // If that succeeds, proceed to futex_wait. Otherwise start the whole loop over again.
- while (@cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic)) |l| {
- if (l == 2 or
- @cmpxchgWeak(i32, &self.linux_lock, 1, 2, AtomicOrder.Acquire, AtomicOrder.Monotonic) == null)
- {
- const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT, 2, null);
- switch (linux.getErrno(rc)) {
- 0, linux.EINTR, linux.EAGAIN => continue,
- linux.EINVAL => unreachable,
- else => unreachable,
- }
+ var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
+ return Held{ .mutex = self };
+ if (c != 2)
+ c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
+ while (c != 0) {
+ const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
+ switch (linux.getErrno(rc)) {
+ 0, linux.EINTR, linux.EAGAIN => {},
+ linux.EINVAL => unreachable,
+ else => unreachable,
}
+ c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
}
} else {
_ = self.spin_lock.acquire();
@@ -74,3 +71,47 @@ pub const Mutex = struct {
return Held{ .mutex = self };
}
};
+
+const Context = struct {
+ mutex: *Mutex,
+ data: i128,
+
+ const incr_count = 10000;
+};
+
+test "std.Mutex" {
+ var direct_allocator = std.heap.DirectAllocator.init();
+ defer direct_allocator.deinit();
+
+ var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
+ defer direct_allocator.allocator.free(plenty_of_memory);
+
+ var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
+ var a = &fixed_buffer_allocator.allocator;
+
+ var mutex = Mutex.init();
+ var context = Context{
+ .mutex = &mutex,
+ .data = 0,
+ };
+
+ const thread_count = 10;
+ var threads: [thread_count]*std.os.Thread = undefined;
+ for (threads) |*t| {
+ t.* = try std.os.spawnThread(&context, worker);
+ }
+ for (threads) |t|
+ t.wait();
+
+ std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);
+}
+
+fn worker(ctx: *Context) void {
+ var i: usize = 0;
+ while (i != Context.incr_count) : (i += 1) {
+ const held = ctx.mutex.acquire();
+ defer held.release();
+
+ ctx.data += 1;
+ }
+}
From 31469daca397b7cdb8c348932a7a3c9e27354fa5 Mon Sep 17 00:00:00 2001
From: emekoi
Date: Thu, 4 Oct 2018 00:23:02 -0500
Subject: [PATCH 070/127] removed unneeded dll extension
---
std/os/windows/ole32.zig | 8 ++++----
std/os/windows/shell32.zig | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/std/os/windows/ole32.zig b/std/os/windows/ole32.zig
index cc737e344c..8f34b45bbf 100644
--- a/std/os/windows/ole32.zig
+++ b/std/os/windows/ole32.zig
@@ -1,9 +1,9 @@
use @import("index.zig");
-pub extern "ole32.dll" stdcallcc fn CoTaskMemFree(pv: LPVOID) void;
-pub extern "ole32.dll" stdcallcc fn CoUninitialize() void;
-pub extern "ole32.dll" stdcallcc fn CoGetCurrentProcess() DWORD;
-pub extern "ole32.dll" stdcallcc fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) HRESULT;
+pub extern "ole32" stdcallcc fn CoTaskMemFree(pv: LPVOID) void;
+pub extern "ole32" stdcallcc fn CoUninitialize() void;
+pub extern "ole32" stdcallcc fn CoGetCurrentProcess() DWORD;
+pub extern "ole32" stdcallcc fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) HRESULT;
pub const COINIT_APARTMENTTHREADED = COINIT.COINIT_APARTMENTTHREADED;
pub const COINIT_MULTITHREADED = COINIT.COINIT_MULTITHREADED;
diff --git a/std/os/windows/shell32.zig b/std/os/windows/shell32.zig
index f10466add3..139babc7a8 100644
--- a/std/os/windows/shell32.zig
+++ b/std/os/windows/shell32.zig
@@ -1,4 +1,4 @@
use @import("index.zig");
-pub extern "shell32.dll" stdcallcc fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*]WCHAR) HRESULT;
+pub extern "shell32" stdcallcc fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*]WCHAR) HRESULT;
From 23b07ad8d25809baa3169f64d9c7be980501352d Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 4 Oct 2018 14:32:55 -0400
Subject: [PATCH 071/127] refactor ir.cpp
Analysis functions no longer return `ZigType *`. Instead they
return `IrInstruction *`.
---
src/all_types.hpp | 6 +-
src/analyze.cpp | 15 +-
src/codegen.cpp | 7 +-
src/ir.cpp | 3812 ++++++++++++++++++++-------------------------
4 files changed, 1716 insertions(+), 2124 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 30d941354a..d7071590d8 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1690,6 +1690,7 @@ struct CodeGen {
Buf cache_dir;
IrInstruction *invalid_instruction;
+ IrInstruction *unreach_instruction;
ConstExprValue const_void_val;
ConstExprValue panic_msg_vals[PanicMsgIdCount];
@@ -2183,7 +2184,10 @@ struct IrInstruction {
// if ref_count is zero and the instruction has no side effects,
// the instruction can be omitted in codegen
size_t ref_count;
- IrInstruction *other;
+ // When analyzing IR, instructions that point to this instruction in the "old ir"
+ // can find the instruction that corresponds to this value in the "new ir"
+ // 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;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 4f8b2f8880..42737a22e5 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -5512,10 +5512,19 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
}
bool ir_get_var_is_comptime(ZigVar *var) {
- if (!var->is_comptime)
+ // The is_comptime field can be left null, which means not comptime.
+ if (var->is_comptime == nullptr)
return false;
- if (var->is_comptime->other)
- return var->is_comptime->other->value.data.x_bool;
+ // When the is_comptime field references an instruction that has to get analyzed, this
+ // is the value.
+ if (var->is_comptime->child != nullptr) {
+ assert(var->is_comptime->child->value.type->id == ZigTypeIdBool);
+ return var->is_comptime->child->value.data.x_bool;
+ }
+ // As an optimization, is_comptime values which are constant are allowed
+ // to be omitted from analysis. In this case, there is no child instruction
+ // and we simply look at the unanalyzed const parent instruction.
+ assert(var->is_comptime->value.type->id == ZigTypeIdBool);
return var->is_comptime->value.data.x_bool;
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index de69b53388..e792fd77aa 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -7279,10 +7279,15 @@ static void init(CodeGen *g) {
define_builtin_types(g);
- g->invalid_instruction = allocate(1);
+ IrInstruction *sentinel_instructions = allocate(2);
+ g->invalid_instruction = &sentinel_instructions[0];
g->invalid_instruction->value.type = g->builtin_types.entry_invalid;
g->invalid_instruction->value.global_refs = allocate(1);
+ g->unreach_instruction = &sentinel_instructions[1];
+ g->unreach_instruction->value.type = g->builtin_types.entry_unreachable;
+ g->unreach_instruction->value.global_refs = allocate(1);
+
g->const_void_val.special = ConstValSpecialStatic;
g->const_void_val.type = g->builtin_types.entry_void;
g->const_void_val.global_refs = allocate(1);
diff --git a/src/ir.cpp b/src/ir.cpp
index abdb3a24a3..09d6fca7e7 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -140,7 +140,7 @@ struct ConstCastErrSetMismatch {
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 ZigType *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
+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);
@@ -261,11 +261,6 @@ static bool instr_is_unreachable(IrInstruction *instruction) {
return instruction->value.type && instruction->value.type->id == ZigTypeIdUnreachable;
}
-static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) {
- new_instruction->other = old_instruction;
- old_instruction->other = new_instruction;
-}
-
static void ir_link_new_bb(IrBasicBlock *new_bb, IrBasicBlock *old_bb) {
new_bb->other = old_bb;
old_bb->other = new_bb;
@@ -919,15 +914,6 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
return &cond_br_instruction->base;
}
-static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block, IrInstruction *is_comptime)
-{
- IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->scope, old_instruction->source_node,
- condition, then_block, else_block, is_comptime);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
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;
@@ -1098,15 +1084,6 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *sou
return &bin_op_instruction->base;
}
-static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_instruction, IrBinOp op_id,
- IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
-{
- IrInstruction *new_instruction = ir_build_bin_op(irb, old_instruction->scope,
- old_instruction->source_node, op_id, op1, op2, safety_check_on);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_var_ptr_x(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var,
ScopeFnDef *crossed_fndef_scope)
{
@@ -1189,15 +1166,6 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
return &instruction->base;
}
-static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *union_ptr, TypeUnionField *type_union_field)
-{
- IrInstruction *new_instruction = ir_build_union_field_ptr(irb, old_instruction->scope,
- old_instruction->source_node, union_ptr, type_union_field);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
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,
@@ -1226,17 +1194,6 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
return &call_instruction->base;
}
-static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction,
- 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_instruction = ir_build_call(irb, old_instruction->scope,
- old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator, new_stack);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source_node,
size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
{
@@ -1256,15 +1213,6 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source
return &phi_instruction->base;
}
-static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instruction,
- size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
-{
- IrInstruction *new_instruction = ir_build_phi(irb, old_instruction->scope, old_instruction->source_node,
- incoming_count, incoming_blocks, incoming_values);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_create_br(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrBasicBlock *dest_block, IrInstruction *is_comptime)
{
@@ -1288,12 +1236,6 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_
return instruction;
}
-static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
- IrInstruction *new_instruction = ir_build_br(irb, old_instruction->scope, old_instruction->source_node, dest_block, nullptr);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes)
@@ -1323,15 +1265,6 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
return &br_instruction->base;
}
-static IrInstruction *ir_build_un_op_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrUnOp op_id, IrInstruction *value)
-{
- IrInstruction *new_instruction = ir_build_un_op(irb, old_instruction->scope,
- old_instruction->source_node, op_id, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *container_type, size_t item_count, IrInstruction **items)
{
@@ -1349,15 +1282,6 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
return &container_init_list_instruction->base;
}
-static IrInstruction *ir_build_container_init_list_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *container_type, size_t item_count, IrInstruction **items)
-{
- IrInstruction *new_instruction = ir_build_container_init_list(irb, old_instruction->scope,
- old_instruction->source_node, container_type, item_count, items);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields)
{
@@ -1389,15 +1313,6 @@ static IrInstruction *ir_build_struct_init(IrBuilder *irb, Scope *scope, AstNode
return &struct_init_instruction->base;
}
-static IrInstruction *ir_build_struct_init_from(IrBuilder *irb, IrInstruction *old_instruction,
- ZigType *struct_type, size_t field_count, IrInstructionStructInitField *fields)
-{
- IrInstruction *new_instruction = ir_build_struct_init(irb, old_instruction->scope,
- old_instruction->source_node, struct_type, field_count, fields);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
{
@@ -1411,15 +1326,6 @@ static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode
return &union_init_instruction->base;
}
-static IrInstruction *ir_build_union_init_from(IrBuilder *irb, IrInstruction *old_instruction,
- ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
-{
- IrInstruction *new_instruction = ir_build_union_init(irb, old_instruction->scope,
- old_instruction->source_node, union_type, field, init_value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionUnreachable *unreachable_instruction =
ir_build_instruction(irb, scope, source_node);
@@ -1428,12 +1334,6 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode
return &unreachable_instruction->base;
}
-static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_build_unreachable(irb, old_instruction->scope, old_instruction->source_node);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *ptr, IrInstruction *value)
{
@@ -1449,15 +1349,6 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
-static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *ptr, IrInstruction *value)
-{
- IrInstruction *new_instruction = ir_build_store_ptr(irb, old_instruction->scope,
- old_instruction->source_node, ptr, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
{
@@ -1476,15 +1367,6 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
return &decl_var_instruction->base;
}
-static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_instruction,
- ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
-{
- IrInstruction *new_instruction = ir_build_var_decl(irb, old_instruction->scope,
- old_instruction->source_node, var, var_type, align_value, init_value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
{
@@ -1512,13 +1394,6 @@ static IrInstruction *ir_build_load_ptr(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_load_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *ptr) {
- IrInstruction *new_instruction = ir_build_load_ptr(irb, old_instruction->scope,
- old_instruction->source_node, ptr);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
IrInstructionTypeOf *instruction = ir_build_instruction(irb, scope, source_node);
instruction->value = value;
@@ -1643,15 +1518,6 @@ static IrInstruction *ir_build_asm(IrBuilder *irb, Scope *scope, AstNode *source
return &instruction->base;
}
-static IrInstruction *ir_build_asm_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction **input_list,
- IrInstruction **output_types, ZigVar **output_vars, size_t return_count, bool has_side_effects)
-{
- IrInstruction *new_instruction = ir_build_asm(irb, old_instruction->scope,
- old_instruction->source_node, input_list, output_types, output_vars, return_count, has_side_effects);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
IrInstructionSizeOf *instruction = ir_build_instruction(irb, scope, source_node);
instruction->type_value = type_value;
@@ -1670,15 +1536,6 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}
-static IrInstruction *ir_build_test_nonnull_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *value)
-{
- IrInstruction *new_instruction = ir_build_test_nonnull(irb, old_instruction->scope,
- old_instruction->source_node, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
bool safety_check_on)
{
@@ -1691,15 +1548,6 @@ static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}
-static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *value, bool safety_check_on)
-{
- IrInstruction *new_instruction = ir_build_unwrap_maybe(irb, old_instruction->scope, old_instruction->source_node,
- value, safety_check_on);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
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;
@@ -1736,12 +1584,6 @@ static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source
return &instruction->base;
}
-static IrInstruction *ir_build_clz_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
- IrInstruction *new_instruction = ir_build_clz(irb, old_instruction->scope, old_instruction->source_node, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
IrInstructionCtz *instruction = ir_build_instruction(irb, scope, source_node);
instruction->value = value;
@@ -1751,12 +1593,6 @@ static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source
return &instruction->base;
}
-static IrInstruction *ir_build_ctz_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
- IrInstruction *new_instruction = ir_build_ctz(irb, old_instruction->scope, old_instruction->source_node, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
IrInstructionPopCount *instruction = ir_build_instruction(irb, scope, source_node);
instruction->value = value;
@@ -1793,16 +1629,6 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
-static IrInstruction *ir_build_switch_br_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *target_value, IrBasicBlock *else_block, size_t case_count,
- IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime, IrInstruction *switch_prongs_void)
-{
- IrInstruction *new_instruction = ir_build_switch_br(irb, old_instruction->scope, old_instruction->source_node,
- target_value, else_block, case_count, cases, is_comptime, switch_prongs_void);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *target_value_ptr)
{
@@ -1917,13 +1743,6 @@ static IrInstruction *ir_build_err_name(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_err_name_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
- IrInstruction *new_instruction = ir_build_err_name(irb, old_instruction->scope,
- old_instruction->source_node, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_c_import(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionCImport *instruction = ir_build_instruction(irb, scope, source_node);
return &instruction->base;
@@ -2005,12 +1824,6 @@ static IrInstruction *ir_build_fence(IrBuilder *irb, Scope *scope, AstNode *sour
return &instruction->base;
}
-static IrInstruction *ir_build_fence_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *order_value, AtomicOrder order) {
- IrInstruction *new_instruction = ir_build_fence(irb, old_instruction->scope, old_instruction->source_node, order_value, order);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_truncate(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
IrInstructionTruncate *instruction = ir_build_instruction(irb, scope, source_node);
instruction->dest_type = dest_type;
@@ -2126,12 +1939,6 @@ static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_bool_not_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
- IrInstruction *new_instruction = ir_build_bool_not(irb, old_instruction->scope, old_instruction->source_node, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_memset(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *dest_ptr, IrInstruction *byte, IrInstruction *count)
{
@@ -2147,14 +1954,6 @@ static IrInstruction *ir_build_memset(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_memset_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *dest_ptr, IrInstruction *byte, IrInstruction *count)
-{
- IrInstruction *new_instruction = ir_build_memset(irb, old_instruction->scope, old_instruction->source_node, dest_ptr, byte, count);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *dest_ptr, IrInstruction *src_ptr, IrInstruction *count)
{
@@ -2170,14 +1969,6 @@ static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *sou
return &instruction->base;
}
-static IrInstruction *ir_build_memcpy_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *dest_ptr, IrInstruction *src_ptr, IrInstruction *count)
-{
- IrInstruction *new_instruction = ir_build_memcpy(irb, old_instruction->scope, old_instruction->source_node, dest_ptr, src_ptr, count);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)
{
@@ -2194,15 +1985,6 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour
return &instruction->base;
}
-static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)
-{
- IrInstruction *new_instruction = ir_build_slice(irb, old_instruction->scope,
- old_instruction->source_node, ptr, start, end, safety_check_on);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
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;
@@ -2243,45 +2025,21 @@ static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstruction *ir_build_breakpoint_from(IrBuilder *irb, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_build_breakpoint(irb, old_instruction->scope, old_instruction->source_node);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_return_address(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionReturnAddress *instruction = ir_build_instruction(irb, scope, source_node);
return &instruction->base;
}
-static IrInstruction *ir_build_return_address_from(IrBuilder *irb, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_build_return_address(irb, old_instruction->scope, old_instruction->source_node);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_frame_address(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionFrameAddress *instruction = ir_build_instruction(irb, scope, source_node);
return &instruction->base;
}
-static IrInstruction *ir_build_frame_address_from(IrBuilder *irb, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_build_frame_address(irb, old_instruction->scope, old_instruction->source_node);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionHandle *instruction = ir_build_instruction(irb, scope, source_node);
return &instruction->base;
}
-static IrInstruction *ir_build_handle_from(IrBuilder *irb, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_build_handle(irb, old_instruction->scope, old_instruction->source_node);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
IrInstruction *result_ptr, ZigType *result_ptr_type)
@@ -2302,16 +2060,6 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstruction *ir_build_overflow_op_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
- IrInstruction *result_ptr, ZigType *result_ptr_type)
-{
- IrInstruction *new_instruction = ir_build_overflow_op(irb, old_instruction->scope, old_instruction->source_node,
- op, type_value, op1, op2, result_ptr, result_ptr_type);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
IrInstructionAlignOf *instruction = ir_build_instruction(irb, scope, source_node);
instruction->type_value = type_value;
@@ -2332,13 +2080,6 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_test_err_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
- IrInstruction *new_instruction = ir_build_test_err(irb, old_instruction->scope, old_instruction->source_node,
- value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *value)
{
@@ -2350,15 +2091,6 @@ static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, Ast
return &instruction->base;
}
-static IrInstruction *ir_build_unwrap_err_code_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *value)
-{
- IrInstruction *new_instruction = ir_build_unwrap_err_code(irb, old_instruction->scope,
- old_instruction->source_node, value);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *value, bool safety_check_on)
{
@@ -2371,15 +2103,6 @@ static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
-static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruction *old_instruction,
- IrInstruction *value, bool safety_check_on)
-{
- IrInstruction *new_instruction = ir_build_unwrap_err_payload(irb, old_instruction->scope,
- old_instruction->source_node, value, safety_check_on);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
-}
-
static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction **param_types, IrInstruction *align_value, IrInstruction *return_type,
IrInstruction *async_allocator_type_value, bool is_var_args)
@@ -3343,6 +3066,10 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
variable_entry->src_arg_index = SIZE_MAX;
variable_entry->value = create_const_vals(1);
+ if (is_comptime != nullptr) {
+ is_comptime->ref_count += 1;
+ }
+
if (name) {
buf_init_from_buf(&variable_entry->name, name);
@@ -9691,10 +9418,10 @@ static void ir_finish_bb(IrAnalyze *ira) {
}
}
-static ZigType *ir_unreach_error(IrAnalyze *ira) {
+static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
ira->old_bb_index = SIZE_MAX;
ira->new_irb.exec->invalid = true;
- return ira->codegen->builtin_types.entry_unreachable;
+ return ira->codegen->unreach_instruction;
}
static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) {
@@ -9714,7 +9441,7 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instru
return true;
}
-static ZigType *ir_inline_bb(IrAnalyze *ira, IrInstruction *source_instruction, IrBasicBlock *old_bb) {
+static IrInstruction *ir_inline_bb(IrAnalyze *ira, IrInstruction *source_instruction, IrBasicBlock *old_bb) {
if (old_bb->debug_id <= ira->old_irb.current_basic_block->debug_id) {
if (!ir_emit_backward_branch(ira, source_instruction))
return ir_unreach_error(ira);
@@ -9722,32 +9449,50 @@ static ZigType *ir_inline_bb(IrAnalyze *ira, IrInstruction *source_instruction,
old_bb->other = ira->old_irb.current_basic_block->other;
ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block);
- return ira->codegen->builtin_types.entry_unreachable;
+ return ira->codegen->unreach_instruction;
}
-static ZigType *ir_finish_anal(IrAnalyze *ira, ZigType *result_type) {
- if (result_type->id == ZigTypeIdUnreachable)
+static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction) {
+ if (instruction->value.type->id == ZigTypeIdUnreachable)
ir_finish_bb(ira);
- return result_type;
+ return instruction;
}
-static IrInstruction *ir_get_const(IrAnalyze *ira, IrInstruction *old_instruction) {
+static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
old_instruction->scope, old_instruction->source_node);
IrInstruction *new_instruction = &const_instruction->base;
+ new_instruction->value.type = ty;
new_instruction->value.special = ConstValSpecialStatic;
return new_instruction;
}
-static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_instruction) {
- IrInstruction *new_instruction = ir_get_const(ira, old_instruction);
- ir_link_new_instruction(new_instruction, old_instruction);
- return &new_instruction->value;
+static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
+ IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
+ result->value.data.x_type = ty;
+ return result;
}
-static ZigType *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) {
- ir_build_const_from(ira, instruction);
- return ira->codegen->builtin_types.entry_void;
+static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instruction, bool value) {
+ IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_bool);
+ result->value.data.x_bool = value;
+ return result;
+}
+
+static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {
+ return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);
+}
+
+static IrInstruction *ir_const_unsigned(IrAnalyze *ira, IrInstruction *source_instruction, uint64_t value) {
+ IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_num_lit_int);
+ bigint_init_unsigned(&result->value.data.x_bigint, value);
+ return result;
+}
+
+static IrInstruction *ir_const_usize(IrAnalyze *ira, IrInstruction *source_instruction, uint64_t value) {
+ IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_usize);
+ bigint_init_unsigned(&result->value.data.x_bigint, value);
+ return result;
}
static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction,
@@ -9756,31 +9501,14 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
{
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type,
ptr_is_const, ptr_is_volatile, PtrLenSingle, ptr_align, 0, 0);
- IrInstruction *const_instr = ir_get_const(ira, instruction);
+ IrInstruction *const_instr = ir_const(ira, instruction, ptr_type);
ConstExprValue *const_val = &const_instr->value;
- const_val->type = ptr_type;
const_val->data.x_ptr.special = ConstPtrSpecialRef;
const_val->data.x_ptr.mut = ptr_mut;
const_val->data.x_ptr.data.ref.pointee = pointee;
return const_instr;
}
-static ZigType *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,
- ConstExprValue *pointee, ZigType *pointee_type,
- ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile)
-{
- IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee,
- pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, 0);
- ir_link_new_instruction(const_instr, instruction);
- return const_instr->value.type;
-}
-
-static ZigType *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) {
- ConstExprValue *const_val = ir_build_const_from(ira, instruction);
- bigint_init_unsigned(&const_val->data.x_bigint, value);
- return ira->codegen->builtin_types.entry_usize;
-}
-
enum UndefAllowed {
UndefOk,
UndefBad,
@@ -11283,14 +11011,6 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
}
}
-static ZigType *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,
- bool is_const, bool is_volatile)
-{
- IrInstruction *result = ir_get_ref(ira, source_instruction, value, is_const, is_volatile);
- ir_link_new_instruction(result, source_instruction);
- return result->value.type;
-}
-
static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
if (type_is_invalid(value->value.type))
return false;
@@ -11485,29 +11205,25 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
return result;
}
-static ZigType *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira,
IrInstructionAddImplicitReturnType *instruction)
{
- IrInstruction *value = instruction->value->other;
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
return ir_unreach_error(ira);
ira->src_implicit_return_type_list.append(value);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->type = ira->codegen->builtin_types.entry_void;
- return out_val->type;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_return(IrAnalyze *ira,
- IrInstructionReturn *return_instruction)
-{
- IrInstruction *value = return_instruction->value->other;
+static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
return ir_unreach_error(ira);
IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
- if (casted_value == ira->codegen->invalid_instruction)
+ if (type_is_invalid(casted_value->value.type))
return ir_unreach_error(ira);
if (casted_value->value.special == ConstValSpecialRuntime &&
@@ -11517,63 +11233,65 @@ static ZigType *ir_analyze_instruction_return(IrAnalyze *ira,
ir_add_error(ira, casted_value, buf_sprintf("function returns address of local variable"));
return ir_unreach_error(ira);
}
- IrInstruction *result = ir_build_return(&ira->new_irb, return_instruction->base.scope,
- return_instruction->base.source_node, casted_value);
+ IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, casted_value);
result->value.type = ira->codegen->builtin_types.entry_unreachable;
- ir_link_new_instruction(result, &return_instruction->base);
- return ir_finish_anal(ira, result->value.type);
+ return ir_finish_anal(ira, result);
}
-static ZigType *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
- ConstExprValue *out_val = ir_build_const_from(ira, &const_instruction->base);
- *out_val = const_instruction->base.value;
- return const_instruction->base.value.type;
+static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ // TODO determine if we need to use copy_const_val here
+ result->value = instruction->base.value;
+ return result;
}
-static ZigType *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
- IrInstruction *op1 = bin_op_instruction->op1->other;
+static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
+ IrInstruction *op1 = bin_op_instruction->op1->child;
if (type_is_invalid(op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op2 = bin_op_instruction->op2->other;
+ IrInstruction *op2 = bin_op_instruction->op2->child;
if (type_is_invalid(op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, bool_type);
if (casted_op1 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, bool_type);
if (casted_op2 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) {
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
ConstExprValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(casted_op1->value.type->id == ZigTypeIdBool);
assert(casted_op2->value.type->id == ZigTypeIdBool);
+ bool result_bool;
if (bin_op_instruction->op_id == IrBinOpBoolOr) {
- out_val->data.x_bool = op1_val->data.x_bool || op2_val->data.x_bool;
+ result_bool = op1_val->data.x_bool || op2_val->data.x_bool;
} else if (bin_op_instruction->op_id == IrBinOpBoolAnd) {
- out_val->data.x_bool = op1_val->data.x_bool && op2_val->data.x_bool;
+ result_bool = op1_val->data.x_bool && op2_val->data.x_bool;
} else {
zig_unreachable();
}
- return bool_type;
+ return ir_const_bool(ira, &bin_op_instruction->base, result_bool);
}
- ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id,
- casted_op1, casted_op2, bin_op_instruction->safety_check_on);
- return bool_type;
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb,
+ bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
+ bin_op_instruction->op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on);
+ result->value.type = bool_type;
+ return result;
}
static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
@@ -11604,15 +11322,15 @@ static bool optional_value_is_null(ConstExprValue *val) {
}
}
-static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
+static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
Error err;
- IrInstruction *op1 = bin_op_instruction->op1->other;
+ IrInstruction *op1 = bin_op_instruction->op1->child;
if (type_is_invalid(op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op2 = bin_op_instruction->op2->other;
+ IrInstruction *op2 = bin_op_instruction->op2->child;
if (type_is_invalid(op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AstNode *source_node = bin_op_instruction->base.source_node;
@@ -11624,9 +11342,7 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
(op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull)))
{
if (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) {
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = (op_id == IrBinOpCmpEq);
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq));
}
IrInstruction *maybe_op;
if (op1->value.type->id == ZigTypeIdNull) {
@@ -11639,11 +11355,10 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
if (instr_is_comptime(maybe_op)) {
ConstExprValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad);
if (!maybe_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool is_null = optional_value_is_null(maybe_val);
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
- return ira->codegen->builtin_types.entry_bool;
+ bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null;
+ return ir_const_bool(ira, &bin_op_instruction->base, bool_result);
}
IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope,
@@ -11651,28 +11366,30 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
is_non_null->value.type = ira->codegen->builtin_types.entry_bool;
if (op_id == IrBinOpCmpEq) {
- ir_build_bool_not_from(&ira->new_irb, &bin_op_instruction->base, is_non_null);
+ IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope,
+ bin_op_instruction->base.source_node, is_non_null);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
} else {
- ir_link_new_instruction(is_non_null, &bin_op_instruction->base);
+ return is_non_null;
}
- return ira->codegen->builtin_types.entry_bool;
} else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) {
ir_add_error_node(ira, source_node, buf_sprintf("comparison against null can only be done with optionals"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) {
if (!is_equality_cmp) {
ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for errors"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *intersect_type = get_error_set_intersection(ira, op1->value.type, op2->value.type, source_node);
if (type_is_invalid(intersect_type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (!resolve_inferred_error_set(ira->codegen, intersect_type, source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
// exception if one of the operators has the type of the empty error set, we allow the comparison
@@ -11689,9 +11406,7 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
} else {
zig_unreachable();
}
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = answer;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
if (!type_is_global_error_set(intersect_type)) {
@@ -11699,7 +11414,7 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
ir_add_error_node(ira, source_node,
buf_sprintf("error sets '%s' and '%s' have no common errors",
buf_ptr(&op1->value.type->name), buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (op1->value.type->data.error_set.err_count == 1 && op2->value.type->data.error_set.err_count == 1) {
bool are_equal = true;
@@ -11711,19 +11426,17 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
} else {
zig_unreachable();
}
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = answer;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
}
if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
ConstExprValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool answer;
bool are_equal = op1_val->data.x_err_set->value == op2_val->data.x_err_set->value;
@@ -11735,21 +11448,20 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
zig_unreachable();
}
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = answer;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
- ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
- op1, op2, bin_op_instruction->safety_check_on);
-
- return ira->codegen->builtin_types.entry_bool;
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb,
+ bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
+ op_id, op1, op2, bin_op_instruction->safety_check_on);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
}
IrInstruction *instructions[] = {op1, op2};
ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);
if (type_is_invalid(resolved_type))
- return resolved_type;
+ return ira->codegen->invalid_instruction;
bool operator_allowed;
switch (resolved_type->id) {
@@ -11794,28 +11506,28 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
if (!operator_allowed) {
ir_add_error_node(ira, source_node,
buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);
if (casted_op1 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, resolved_type);
if (casted_op2 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown)))
- return resolved_type;
+ return ira->codegen->invalid_instruction;
bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = one_possible_value ? &casted_op2->value : ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool answer;
if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
@@ -11835,9 +11547,7 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
}
}
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = answer;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
// some comparisons with unsigned numbers can be evaluated
@@ -11847,13 +11557,13 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
if (instr_is_comptime(casted_op1)) {
known_left_val = ir_resolve_const(ira, casted_op1, UndefBad);
if (known_left_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
flipped_op_id = op_id;
} else if (instr_is_comptime(casted_op2)) {
known_left_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (known_left_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (op_id == IrBinOpCmpLessThan) {
flipped_op_id = IrBinOpCmpGreaterThan;
@@ -11873,16 +11583,15 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
(flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan))
{
bool answer = (flipped_op_id == IrBinOpCmpLessOrEq);
- ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
- out_val->data.x_bool = answer;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
}
- ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
- casted_op1, casted_op2, bin_op_instruction->safety_check_on);
-
- return ira->codegen->builtin_types.entry_bool;
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb,
+ bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
+ op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
}
static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
@@ -12065,21 +11774,21 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
return 0;
}
-static ZigType *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
- IrInstruction *op1 = bin_op_instruction->op1->other;
+static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
+ IrInstruction *op1 = bin_op_instruction->op1->child;
if (type_is_invalid(op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (op1->value.type->id != ZigTypeIdInt && op1->value.type->id != ZigTypeIdComptimeInt) {
ir_add_error(ira, &bin_op_instruction->base,
buf_sprintf("bit shifting operation expected integer type, found '%s'",
buf_ptr(&op1->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *op2 = bin_op_instruction->op2->other;
+ IrInstruction *op2 = bin_op_instruction->op2->child;
if (type_is_invalid(op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_op2;
IrBinOp op_id = bin_op_instruction->op_id;
@@ -12094,7 +11803,7 @@ static ZigType *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_
Buf *val_buf = buf_alloc();
bigint_append_buf(val_buf, &casted_op2->value.data.x_bigint, 10);
ir_add_error(ira, casted_op2, buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,
@@ -12116,71 +11825,70 @@ static ZigType *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_
buf_sprintf("value %s cannot fit into type %s",
buf_ptr(val_buf),
buf_ptr(&shift_amt_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
if (casted_op2 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {
ConstExprValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result_instruction = ir_get_const(ira, &bin_op_instruction->base);
- ir_link_new_instruction(result_instruction, &bin_op_instruction->base);
- ConstExprValue *out_val = &result_instruction->value;
+ IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);
int err;
- if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, out_val))) {
+ if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) {
if (err == ErrorOverflow) {
ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (err == ErrorShiftedOutOneBits) {
ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
zig_unreachable();
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false);
- return op1->value.type;
+ return result_instruction;
} else if (op1->value.type->id == ZigTypeIdComptimeInt) {
ir_add_error(ira, &bin_op_instruction->base,
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value.data.x_bigint) == CmpEQ) {
IrInstruction *result = ir_build_cast(&ira->new_irb, bin_op_instruction->base.scope,
bin_op_instruction->base.source_node, op1->value.type, op1, CastOpNoop);
result->value.type = op1->value.type;
- ir_link_new_instruction(result, &bin_op_instruction->base);
- return result->value.type;
+ return result;
}
- ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.scope,
+ bin_op_instruction->base.source_node, op_id,
op1, casted_op2, bin_op_instruction->safety_check_on);
- return op1->value.type;
+ result->value.type = op1->value.type;
+ return result;
}
-static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
- IrInstruction *op1 = bin_op_instruction->op1->other;
+static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
+ IrInstruction *op1 = instruction->op1->child;
if (type_is_invalid(op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op2 = bin_op_instruction->op2->other;
+ IrInstruction *op2 = instruction->op2->child;
if (type_is_invalid(op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrBinOp op_id = bin_op_instruction->op_id;
+ IrBinOp op_id = instruction->op_id;
// look for pointer math
if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
@@ -12188,19 +11896,18 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
{
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
if (casted_op2 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.scope,
- bin_op_instruction->base.source_node, op_id, op1, casted_op2, true);
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, op_id, op1, casted_op2, true);
result->value.type = op1->value.type;
- ir_link_new_instruction(result, &bin_op_instruction->base);
- return result->value.type;
+ return result;
}
IrInstruction *instructions[] = {op1, op2};
- ZigType *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, nullptr, instructions, 2);
+ ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);
if (type_is_invalid(resolved_type))
- return resolved_type;
+ return ira->codegen->invalid_instruction;
bool is_int = resolved_type->id == ZigTypeIdInt || resolved_type->id == ZigTypeIdComptimeInt;
bool is_float = resolved_type->id == ZigTypeIdFloat || resolved_type->id == ZigTypeIdComptimeFloat;
@@ -12220,11 +11927,11 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
ConstExprValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (bigint_cmp_zero(&op2_val->data.x_bigint) == CmpEQ) {
// the division by zero error will be caught later, but we don't have a
@@ -12243,11 +11950,11 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
}
}
if (!ok) {
- ir_add_error(ira, &bin_op_instruction->base,
+ ir_add_error(ira, &instruction->base,
buf_sprintf("division with '%s' and '%s': signed integers must use @divTrunc, @divFloor, or @divExact",
buf_ptr(&op1->value.type->name),
buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
op_id = IrBinOpDivTrunc;
@@ -12258,12 +11965,12 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
ConstExprValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (is_int) {
ConstExprValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (bigint_cmp_zero(&op2->value.data.x_bigint) == CmpEQ) {
// the division by zero error will be caught later, but we don't
@@ -12279,11 +11986,11 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
} else {
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, resolved_type);
if (casted_op2 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (float_cmp_zero(&casted_op2->value) == CmpEQ) {
// the division by zero error will be caught later, but we don't
@@ -12299,11 +12006,11 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
}
}
if (!ok) {
- ir_add_error(ira, &bin_op_instruction->base,
+ ir_add_error(ira, &instruction->base,
buf_sprintf("remainder division with '%s' and '%s': signed integers and floats must use @rem or @mod",
buf_ptr(&op1->value.type->name),
buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
op_id = IrBinOpRemRem;
@@ -12324,12 +12031,12 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
{
// float
} else {
- AstNode *source_node = bin_op_instruction->base.source_node;
+ AstNode *source_node = instruction->base.source_node;
ir_add_error_node(ira, source_node,
buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
buf_ptr(&op1->value.type->name),
buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (resolved_type->id == ZigTypeIdComptimeInt) {
@@ -12344,72 +12051,70 @@ static ZigType *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_o
IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);
if (casted_op1 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, resolved_type);
if (casted_op2 == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) {
ConstExprValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
if (op1_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
if (op2_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result_instruction = ir_get_const(ira, &bin_op_instruction->base);
- ir_link_new_instruction(result_instruction, &bin_op_instruction->base);
- ConstExprValue *out_val = &result_instruction->value;
+ IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);
int err;
- if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, out_val))) {
+ if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) {
if (err == ErrorDivByZero) {
- ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("division by zero"));
- return ira->codegen->builtin_types.entry_invalid;
+ ir_add_error(ira, &instruction->base, buf_sprintf("division by zero"));
+ return ira->codegen->invalid_instruction;
} else if (err == ErrorOverflow) {
- ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow"));
- return ira->codegen->builtin_types.entry_invalid;
+ ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow"));
+ return ira->codegen->invalid_instruction;
} else if (err == ErrorExactDivRemainder) {
- ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact division had a remainder"));
- return ira->codegen->builtin_types.entry_invalid;
+ ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder"));
+ return ira->codegen->invalid_instruction;
} else if (err == ErrorNegativeDenominator) {
- ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("negative denominator"));
- return ira->codegen->builtin_types.entry_invalid;
+ ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator"));
+ return ira->codegen->invalid_instruction;
} else {
zig_unreachable();
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false);
- return resolved_type;
+ return result_instruction;
}
- ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
- casted_op1, casted_op2, bin_op_instruction->safety_check_on);
- return resolved_type;
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, op_id, casted_op1, casted_op2, instruction->safety_check_on);
+ result->value.type = resolved_type;
+ return result;
}
-
-static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {
- IrInstruction *op1 = instruction->op1->other;
+static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {
+ IrInstruction *op1 = instruction->op1->child;
ZigType *op1_type = op1->value.type;
if (type_is_invalid(op1_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op2 = instruction->op2->other;
+ IrInstruction *op2 = instruction->op2->child;
ZigType *op2_type = op2->value.type;
if (type_is_invalid(op2_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
if (!op1_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op2_val = ir_resolve_const(ira, op2, UndefBad);
if (!op2_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *op1_array_val;
size_t op1_array_index;
@@ -12441,7 +12146,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
} else {
ir_add_error(ira, op1,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ConstExprValue *op2_array_val;
@@ -12452,7 +12157,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
buf_ptr(&child_type->name),
buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
op2_array_val = op2_val;
op2_array_index = 0;
@@ -12466,7 +12171,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
buf_ptr(&child_type->name),
buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
@@ -12477,7 +12182,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
buf_ptr(&child_type->name),
buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
@@ -12489,22 +12194,23 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
} else {
ir_add_error(ira, op2,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ // The type of result is populated in the following if blocks
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ ConstExprValue *out_val = &result->value;
- ZigType *result_type;
ConstExprValue *out_array_val;
size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {
- result_type = get_array_type(ira->codegen, child_type, new_len);
+ result->value.type = get_array_type(ira->codegen, child_type, new_len);
out_array_val = out_val;
} else if (is_slice(op1_type) || is_slice(op2_type)) {
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
true, false, PtrLenUnknown, 0, 0, 0);
- result_type = get_slice_type(ira->codegen, ptr_type);
+ result->value.type = get_slice_type(ira->codegen, ptr_type);
out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic;
out_array_val->type = get_array_type(ira->codegen, child_type, new_len);
@@ -12524,7 +12230,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
new_len += 1; // null byte
// TODO make this `[*]null T` instead of `[*]T`
- result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0);
+ result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0);
out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic;
@@ -12538,7 +12244,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
if (op1_array_val->data.x_array.special == ConstArraySpecialUndef &&
op2_array_val->data.x_array.special == ConstArraySpecialUndef) {
out_array_val->data.x_array.special = ConstArraySpecialUndef;
- return result_type;
+ return result;
}
out_array_val->data.x_array.data.s_none.elements = create_const_vals(new_len);
@@ -12560,30 +12266,30 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
}
assert(next_index == new_len);
- return result_type;
+ return result;
}
-static ZigType *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) {
- IrInstruction *op1 = instruction->op1->other;
+static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) {
+ IrInstruction *op1 = instruction->op1->child;
if (type_is_invalid(op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op2 = instruction->op2->other;
+ IrInstruction *op2 = instruction->op2->child;
if (type_is_invalid(op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *array_val = ir_resolve_const(ira, op1, UndefBad);
if (!array_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
uint64_t mult_amt;
if (!ir_resolve_usize(ira, op2, &mult_amt))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *array_type = op1->value.type;
if (array_type->id != ZigTypeIdArray) {
ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
uint64_t old_array_len = array_type->data.array.len;
@@ -12592,15 +12298,17 @@ static ZigType *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instru
if (mul_u64_overflow(old_array_len, mult_amt, &new_array_len))
{
ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ ZigType *child_type = array_type->data.array.child_type;
+
+ IrInstruction *result = ir_const(ira, &instruction->base,
+ get_array_type(ira->codegen, child_type, new_array_len));
+ ConstExprValue *out_val = &result->value;
if (array_val->data.x_array.special == ConstArraySpecialUndef) {
out_val->data.x_array.special = ConstArraySpecialUndef;
-
- ZigType *child_type = array_type->data.array.child_type;
- return get_array_type(ira->codegen, child_type, new_array_len);
+ return result;
}
// TODO optimize the buf case
@@ -12616,45 +12324,42 @@ static ZigType *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instru
}
assert(i == new_array_len);
- ZigType *child_type = array_type->data.array.child_type;
- return get_array_type(ira->codegen, child_type, new_array_len);
+ return result;
}
-static ZigType *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {
- ZigType *op1_type = ir_resolve_type(ira, instruction->op1->other);
+static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {
+ ZigType *op1_type = ir_resolve_type(ira, instruction->op1->child);
if (type_is_invalid(op1_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (op1_type->id != ZigTypeIdErrorSet) {
ir_add_error(ira, instruction->op1,
buf_sprintf("expected error set type, found '%s'", buf_ptr(&op1_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ZigType *op2_type = ir_resolve_type(ira, instruction->op2->other);
+ ZigType *op2_type = ir_resolve_type(ira, instruction->op2->child);
if (type_is_invalid(op2_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (op2_type->id != ZigTypeIdErrorSet) {
ir_add_error(ira, instruction->op2,
buf_sprintf("expected error set type, found '%s'", buf_ptr(&op2_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (type_is_global_error_set(op1_type) ||
type_is_global_error_set(op2_type))
{
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = ira->codegen->builtin_types.entry_global_error_set;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_global_error_set);
}
- if (!resolve_inferred_error_set(ira->codegen, op1_type, instruction->op1->other->source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ if (!resolve_inferred_error_set(ira->codegen, op1_type, instruction->op1->child->source_node)) {
+ return ira->codegen->invalid_instruction;
}
- if (!resolve_inferred_error_set(ira->codegen, op2_type, instruction->op2->other->source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ if (!resolve_inferred_error_set(ira->codegen, op2_type, instruction->op2->child->source_node)) {
+ return ira->codegen->invalid_instruction;
}
ErrorTableEntry **errors = allocate(ira->codegen->errors_by_index.length);
@@ -12666,13 +12371,10 @@ static ZigType *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *
ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type);
free(errors);
-
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = result_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, result_type);
}
-static ZigType *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
+static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
IrBinOp op_id = bin_op_instruction->op_id;
switch (op_id) {
case IrBinOpInvalid:
@@ -12719,25 +12421,25 @@ static ZigType *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructionBinOp
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {
+static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {
Error err;
ZigVar *var = decl_var_instruction->var;
- IrInstruction *init_value = decl_var_instruction->init_value->other;
+ IrInstruction *init_value = decl_var_instruction->init_value->child;
if (type_is_invalid(init_value->value.type)) {
var->value->type = ira->codegen->builtin_types.entry_invalid;
- return var->value->type;
+ return ira->codegen->invalid_instruction;
}
ZigType *explicit_type = nullptr;
IrInstruction *var_type = nullptr;
if (decl_var_instruction->var_type != nullptr) {
- var_type = decl_var_instruction->var_type->other;
+ var_type = decl_var_instruction->var_type->child;
ZigType *proposed_type = ir_resolve_type(ira, var_type);
explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
if (type_is_invalid(explicit_type)) {
var->value->type = ira->codegen->builtin_types.entry_invalid;
- return var->value->type;
+ return ira->codegen->invalid_instruction;
}
}
@@ -12815,19 +12517,17 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
assert(var->value->type);
if (type_is_invalid(result_type)) {
- decl_var_instruction->base.other = &decl_var_instruction->base;
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &decl_var_instruction->base);
}
if (decl_var_instruction->align_value == nullptr) {
if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
var->value->type = ira->codegen->builtin_types.entry_invalid;
- decl_var_instruction->base.other = &decl_var_instruction->base;
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &decl_var_instruction->base);
}
var->align_bytes = get_abi_alignment(ira->codegen, result_type);
} else {
- if (!ir_resolve_align(ira, decl_var_instruction->align_value->other, &var->align_bytes)) {
+ if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
var->value->type = ira->codegen->builtin_types.entry_invalid;
}
}
@@ -12839,43 +12539,44 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
copy_const_val(mem_slot, &casted_init_value->value, !is_comptime_var || var->gen_is_const);
if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {
- ir_build_const_from(ira, &decl_var_instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &decl_var_instruction->base);
}
}
} else if (is_comptime_var) {
ir_add_error(ira, &decl_var_instruction->base,
buf_sprintf("cannot store runtime value in compile time variable"));
var->value->type = ira->codegen->builtin_types.entry_invalid;
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, nullptr, casted_init_value);
-
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
if (fn_entry)
fn_entry->variable_list.append(var);
- return ira->codegen->builtin_types.entry_void;
+ IrInstruction *result = ir_build_var_decl(&ira->new_irb,
+ decl_var_instruction->base.scope, decl_var_instruction->base.source_node,
+ var, var_type, nullptr, casted_init_value);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
}
-static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
- IrInstruction *name = instruction->name->other;
+static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
+ IrInstruction *name = instruction->name->child;
Buf *symbol_name = ir_resolve_str(ira, name);
if (symbol_name == nullptr) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
GlobalLinkageId global_linkage_id = GlobalLinkageIdStrong;
if (instruction->linkage != nullptr) {
- IrInstruction *linkage_value = instruction->linkage->other;
+ IrInstruction *linkage_value = instruction->linkage->child;
if (!ir_resolve_global_linkage(ira, linkage_value, &global_linkage_id)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -13023,8 +12724,7 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor
break;
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {
@@ -13032,59 +12732,58 @@ static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {
return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing;
}
-static ZigType *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
IrInstructionErrorReturnTrace *instruction)
{
if (instruction->optional == IrInstructionErrorReturnTrace::Null) {
ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen);
ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type);
if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base, optional_type);
+ ConstExprValue *out_val = &result->value;
assert(get_codegen_ptr_type(optional_type) != nullptr);
out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
out_val->data.x_ptr.data.hard_coded_addr.addr = 0;
- return optional_type;
+ return result;
}
IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, instruction->optional);
- ir_link_new_instruction(new_instruction, &instruction->base);
- return optional_type;
+ new_instruction->value.type = optional_type;
+ return new_instruction;
} else {
assert(ira->codegen->have_err_ret_tracing);
IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, instruction->optional);
- ir_link_new_instruction(new_instruction, &instruction->base);
- return get_ptr_to_stack_trace_type(ira->codegen);
+ new_instruction->value.type = get_ptr_to_stack_trace_type(ira->codegen);
+ return new_instruction;
}
}
-static ZigType *ir_analyze_instruction_error_union(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,
IrInstructionErrorUnion *instruction)
{
Error err;
- ZigType *err_set_type = ir_resolve_type(ira, instruction->err_set->other);
+ ZigType *err_set_type = ir_resolve_type(ira, instruction->err_set->child);
if (type_is_invalid(err_set_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ZigType *payload_type = ir_resolve_type(ira, instruction->payload->other);
+ ZigType *payload_type = ir_resolve_type(ira, instruction->payload->child);
if (type_is_invalid(payload_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (err_set_type->id != ZigTypeIdErrorSet) {
- ir_add_error(ira, instruction->err_set->other,
+ ir_add_error(ira, instruction->err_set->child,
buf_sprintf("expected error set type, found type '%s'",
buf_ptr(&err_set_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = result_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, result_type);
}
IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, ImplicitAllocatorId id) {
@@ -13362,7 +13061,7 @@ no_mem_slot:
return var_ptr_instruction;
}
-static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
+static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
{
@@ -13382,7 +13081,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
size_t call_param_count = call_instruction->arg_count + first_arg_1_or_0;
for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
- ConstExprValue *arg_tuple_value = &call_instruction->args[i]->other->value;
+ ConstExprValue *arg_tuple_value = &call_instruction->args[i]->child->value;
if (arg_tuple_value->type->id == ZigTypeIdArgTuple) {
call_param_count -= 1;
call_param_count += arg_tuple_value->data.x_arg_tuple.end_index -
@@ -13398,21 +13097,21 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
if (fn_proto_node) {
add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_type_id->cc == CallingConventionAsync && !call_instruction->is_async) {
ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("must use async keyword to call async function"));
if (fn_proto_node) {
add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_type_id->cc != CallingConventionAsync && call_instruction->is_async) {
ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("cannot use async keyword to call non-async function"));
if (fn_proto_node) {
add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
@@ -13424,7 +13123,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
add_error_note(ira->codegen, msg, fn_proto_node,
buf_sprintf("declared here"));
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (src_param_count != call_param_count) {
ErrorMsg *msg = ir_add_error_node(ira, source_node,
@@ -13433,18 +13132,18 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
add_error_note(ira->codegen, msg, fn_proto_node,
buf_sprintf("declared here"));
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (comptime_fn_call) {
// No special handling is needed for compile time evaluation of generic functions.
if (!fn_entry || fn_entry->body_node == nullptr) {
ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (!ir_emit_backward_branch(ira, &call_instruction->base))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
// Fork a scope of the function with known values for the parameters.
Scope *exec_scope = &fn_entry->fndef_scope->base;
@@ -13457,7 +13156,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
if (fn_type_id->next_param_index >= 1) {
ZigType *param_type = fn_type_id->param_info[next_proto_i].type;
if (type_is_invalid(param_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
first_arg_known_bare = param_type->id != ZigTypeIdPointer;
}
@@ -13467,39 +13166,39 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
} else {
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
if (type_is_invalid(first_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, first_arg, &exec_scope, &next_proto_i))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_proto_node->data.fn_proto.is_var_args) {
ir_add_error(ira, &call_instruction->base,
buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {
- IrInstruction *old_arg = call_instruction->args[call_i]->other;
+ IrInstruction *old_arg = call_instruction->args[call_i]->child;
if (type_is_invalid(old_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
ZigType *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node);
if (type_is_invalid(specified_return_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *return_type;
ZigType *inferred_err_set_type = nullptr;
if (fn_proto_node->data.fn_proto.auto_err_set) {
inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry);
if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
} else {
return_type = specified_return_type;
@@ -13542,12 +13241,14 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
}
if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base);
- *out_val = result->value;
- return ir_finish_anal(ira, return_type);
+ IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);
+ // TODO should we use copy_const_val?
+ new_instruction->value = result->value;
+ new_instruction->value.type = return_type;
+ return ir_finish_anal(ira, new_instruction);
}
IrInstruction *casted_new_stack = nullptr;
@@ -13555,28 +13256,28 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, 0, 0, 0);
ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
- IrInstruction *new_stack = call_instruction->new_stack->other;
+ IrInstruction *new_stack = call_instruction->new_stack->child;
if (type_is_invalid(new_stack->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
if (type_is_invalid(casted_new_stack->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_type->data.fn.is_generic) {
if (!fn_entry) {
ir_add_error(ira, call_instruction->fn_ref,
buf_sprintf("calling a generic function requires compile-time known function value"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
// Count the arguments of the function type id we are creating
size_t new_fn_arg_count = first_arg_1_or_0;
for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {
- IrInstruction *arg = call_instruction->args[call_i]->other;
+ IrInstruction *arg = call_instruction->args[call_i]->child;
if (type_is_invalid(arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (arg->value.type->id == ZigTypeIdArgTuple) {
new_fn_arg_count += arg->value.data.x_arg_tuple.end_index - arg->value.data.x_arg_tuple.start_index;
@@ -13614,7 +13315,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
if (fn_type_id->next_param_index >= 1) {
ZigType *param_type = fn_type_id->param_info[next_proto_i].type;
if (type_is_invalid(param_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
first_arg_known_bare = param_type->id != ZigTypeIdPointer;
}
@@ -13624,13 +13325,13 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
} else {
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
if (type_is_invalid(first_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, &impl_fn->child_scope,
&next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn))
{
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -13640,9 +13341,9 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
assert(parent_fn_entry);
for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {
- IrInstruction *arg = call_instruction->args[call_i]->other;
+ IrInstruction *arg = call_instruction->args[call_i]->child;
if (type_is_invalid(arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (arg->value.type->id == ZigTypeIdArgTuple) {
for (size_t arg_tuple_i = arg->value.data.x_arg_tuple.start_index;
@@ -13660,20 +13361,20 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
if (arg_var == nullptr) {
ir_add_error(ira, arg,
buf_sprintf("compiler bug: var args can't handle void. https://github.com/ziglang/zig/issues/557"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstruction *arg_var_ptr_inst = ir_get_var_ptr(ira, arg, arg_var);
if (type_is_invalid(arg_var_ptr_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst);
if (type_is_invalid(arg_tuple_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg_tuple_arg, &impl_fn->child_scope,
&next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn))
{
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
} else {
@@ -13688,7 +13389,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope,
&next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn))
{
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
}
@@ -13724,18 +13425,18 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
ZigType *specified_return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node);
if (type_is_invalid(specified_return_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (fn_proto_node->data.fn_proto.auto_err_set) {
ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn);
if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
inst_fn_type_id.return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
} else {
inst_fn_type_id.return_type = specified_return_type;
}
if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (type_requires_comptime(specified_return_type)) {
// Throw out our work and call the function as if it were comptime.
@@ -13748,7 +13449,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
if (async_allocator_type_node != nullptr) {
ZigType *async_allocator_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, async_allocator_type_node);
if (type_is_invalid(async_allocator_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
inst_fn_type_id.async_allocator_type = async_allocator_type;
}
IrInstruction *uncasted_async_allocator_inst;
@@ -13756,18 +13457,18 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base,
ImplicitAllocatorIdLocalVar);
if (type_is_invalid(uncasted_async_allocator_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
- uncasted_async_allocator_inst = call_instruction->async_allocator->other;
+ uncasted_async_allocator_inst = call_instruction->async_allocator->child;
if (type_is_invalid(uncasted_async_allocator_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (inst_fn_type_id.async_allocator_type == nullptr) {
inst_fn_type_id.async_allocator_type = uncasted_async_allocator_inst->value.type;
}
async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, inst_fn_type_id.async_allocator_type);
if (type_is_invalid(async_allocator_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
auto existing_entry = ira->codegen->generic_table.put_unique(generic_id, impl_fn);
@@ -13778,7 +13479,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
// finish instantiating the function
impl_fn->type_entry = get_fn_type(ira->codegen, &inst_fn_type_id);
if (type_is_invalid(impl_fn->type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
impl_fn->ir_executable.source_node = call_instruction->base.source_node;
impl_fn->ir_executable.parent_exec = ira->new_irb.exec;
@@ -13797,21 +13498,22 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
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_link_new_instruction(result, &call_instruction->base);
+ 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->value.type);
+ return ir_finish_anal(ira, result);
}
assert(async_allocator_inst == nullptr);
- IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
+ 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);
+ new_call_instruction->value.type = return_type;
ir_add_alloca(ira, new_call_instruction, return_type);
- return ir_finish_anal(ira, return_type);
+ return ir_finish_anal(ira, new_call_instruction);
}
ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
@@ -13829,7 +13531,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
ZigType *param_type = fn_type_id->param_info[next_arg_index].type;
if (type_is_invalid(param_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *first_arg;
if (param_type->id == ZigTypeIdPointer &&
@@ -13839,28 +13541,28 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
} else {
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
if (type_is_invalid(first_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstruction *casted_arg = ir_implicit_cast(ira, first_arg, param_type);
if (type_is_invalid(casted_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
casted_args[next_arg_index] = casted_arg;
next_arg_index += 1;
}
for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {
- IrInstruction *old_arg = call_instruction->args[call_i]->other;
+ IrInstruction *old_arg = call_instruction->args[call_i]->child;
if (type_is_invalid(old_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_arg;
if (next_arg_index < src_param_count) {
ZigType *param_type = fn_type_id->param_info[next_arg_index].type;
if (type_is_invalid(param_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
casted_arg = ir_implicit_cast(ira, old_arg, param_type);
if (type_is_invalid(casted_arg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
casted_arg = old_arg;
}
@@ -13873,7 +13575,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
ZigType *return_type = fn_type_id->return_type;
if (type_is_invalid(return_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (call_instruction->is_async) {
IrInstruction *uncasted_async_allocator_inst;
@@ -13881,41 +13583,41 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base,
ImplicitAllocatorIdLocalVar);
if (type_is_invalid(uncasted_async_allocator_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
- uncasted_async_allocator_inst = call_instruction->async_allocator->other;
+ uncasted_async_allocator_inst = call_instruction->async_allocator->child;
if (type_is_invalid(uncasted_async_allocator_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstruction *async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, fn_type_id->async_allocator_type);
if (type_is_invalid(async_allocator_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count,
- async_allocator_inst);
- ir_link_new_instruction(result, &call_instruction->base);
+ 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->value.type);
+ return ir_finish_anal(ira, result);
}
if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && fn_inline == FnInlineNever) {
ir_add_error(ira, &call_instruction->base,
buf_sprintf("no-inline call of inline function"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
+ 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);
-
+ new_call_instruction->value.type = return_type;
ir_add_alloca(ira, new_call_instruction, return_type);
- return ir_finish_anal(ira, return_type);
+ return ir_finish_anal(ira, new_call_instruction);
}
-static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
- IrInstruction *fn_ref = call_instruction->fn_ref->other;
+static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
+ IrInstruction *fn_ref = call_instruction->fn_ref->child;
if (type_is_invalid(fn_ref->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool is_comptime = call_instruction->is_comptime ||
ir_should_inline(ira->new_irb.exec, call_instruction->base.scope);
@@ -13924,28 +13626,26 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c
if (fn_ref->value.type->id == ZigTypeIdMetaType) {
ZigType *dest_type = ir_resolve_type(ira, fn_ref);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t actual_param_count = call_instruction->arg_count;
if (actual_param_count != 1) {
ir_add_error_node(ira, call_instruction->base.source_node,
buf_sprintf("cast expression expects exactly one parameter"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *arg = call_instruction->args[0]->other;
+ IrInstruction *arg = call_instruction->args[0]->child;
IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg);
if (type_is_invalid(cast_instruction->value.type))
- return ira->codegen->builtin_types.entry_invalid;
-
- ir_link_new_instruction(cast_instruction, &call_instruction->base);
- return ir_finish_anal(ira, cast_instruction->value.type);
+ return ira->codegen->invalid_instruction;
+ return ir_finish_anal(ira, cast_instruction);
} else if (fn_ref->value.type->id == ZigTypeIdFn) {
ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);
if (fn_table_entry == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,
fn_ref, nullptr, is_comptime, call_instruction->fn_inline);
} else if (fn_ref->value.type->id == ZigTypeIdBoundFn) {
@@ -13957,7 +13657,7 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c
} else {
ir_add_error_node(ira, fn_ref->source_node,
buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -13967,7 +13667,7 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c
} else {
ir_add_error_node(ira, fn_ref->source_node,
buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -14008,14 +13708,14 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
return ErrorNone;
}
-static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
+static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
Error err;
- IrInstruction *value = un_op_instruction->value->other;
+ IrInstruction *value = un_op_instruction->value->child;
ZigType *type_entry = ir_resolve_type(ira, value);
if (type_is_invalid(type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = ensure_complete_type(ira->codegen, type_entry)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (type_entry->id) {
case ZigTypeIdInvalid:
@@ -14042,27 +13742,23 @@ static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instru
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
- {
- ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
- out_val->data.x_type = get_optional_type(ira->codegen, type_entry);
- return ira->codegen->builtin_types.entry_type;
- }
+ return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
case ZigTypeIdUnreachable:
case ZigTypeIdOpaque:
ir_add_error_node(ira, un_op_instruction->base.source_node,
buf_sprintf("type '%s' not optional", buf_ptr(&type_entry->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
zig_unreachable();
}
-static ZigType *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
- IrInstruction *value = un_op_instruction->value->other;
+static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) {
+ IrInstruction *value = instruction->value->child;
ZigType *expr_type = value->value.type;
if (type_is_invalid(expr_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);
+ bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
bool is_float = (expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat);
@@ -14072,9 +13768,10 @@ static ZigType *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_ins
if (instr_is_comptime(value)) {
ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
if (!target_const_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
+ ConstExprValue *out_val = &result->value;
if (is_float) {
float_negate(out_val, target_const_val);
} else if (is_wrap_op) {
@@ -14084,92 +13781,96 @@ static ZigType *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_ins
bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);
}
if (is_wrap_op || is_float || expr_type->id == ZigTypeIdComptimeInt) {
- return expr_type;
+ return result;
}
if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {
- ir_add_error(ira, &un_op_instruction->base, buf_sprintf("negation caused overflow"));
- return ira->codegen->builtin_types.entry_invalid;
+ ir_add_error(ira, &instruction->base, buf_sprintf("negation caused overflow"));
+ return ira->codegen->invalid_instruction;
}
- return expr_type;
+ return result;
}
- ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, un_op_instruction->op_id, value);
- return expr_type;
+ IrInstruction *result = ir_build_un_op(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node,
+ instruction->op_id, value);
+ result->value.type = expr_type;
+ return result;
}
const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
- ir_add_error(ira, &un_op_instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ ir_add_error(ira, &instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
+ return ira->codegen->invalid_instruction;
}
-static ZigType *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
+ IrInstruction *value = instruction->value->child;
ZigType *expr_type = value->value.type;
if (type_is_invalid(expr_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (expr_type->id == ZigTypeIdInt) {
if (instr_is_comptime(value)) {
ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
if (target_const_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_not(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
+ IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
+ bigint_not(&result->value.data.x_bigint, &target_const_val->data.x_bigint,
expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
- return expr_type;
+ return result;
}
- ir_build_un_op_from(&ira->new_irb, &instruction->base, IrUnOpBinNot, value);
- return expr_type;
+ IrInstruction *result = ir_build_un_op(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, IrUnOpBinNot, value);
+ result->value.type = expr_type;
+ return result;
}
ir_add_error(ira, &instruction->base,
buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
-static ZigType *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
- IrUnOp op_id = un_op_instruction->op_id;
+static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *instruction) {
+ IrUnOp op_id = instruction->op_id;
switch (op_id) {
case IrUnOpInvalid:
zig_unreachable();
case IrUnOpBinNot:
- return ir_analyze_bin_not(ira, un_op_instruction);
+ return ir_analyze_bin_not(ira, instruction);
case IrUnOpNegation:
case IrUnOpNegationWrap:
- return ir_analyze_negation(ira, un_op_instruction);
+ return ir_analyze_negation(ira, instruction);
case IrUnOpDereference: {
- IrInstruction *ptr = un_op_instruction->value->other;
+ IrInstruction *ptr = instruction->value->child;
if (type_is_invalid(ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = ptr->value.type;
if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.ptr_len == PtrLenUnknown) {
- ir_add_error_node(ira, un_op_instruction->base.source_node,
+ ir_add_error_node(ira, instruction->base.source_node,
buf_sprintf("index syntax required for unknown-length pointer type '%s'",
buf_ptr(&ptr_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
// this dereference is always an rvalue because in the IR gen we identify lvalue and emit
// one of the ptr instructions
- IrInstruction *result = ir_get_deref(ira, &un_op_instruction->base, ptr);
+ IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);
if (result == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
- ir_link_new_instruction(result, &un_op_instruction->base);
- return result->value.type;
+ return ira->codegen->invalid_instruction;
+ return result;
}
case IrUnOpOptional:
- return ir_analyze_maybe(ira, un_op_instruction);
+ return ir_analyze_maybe(ira, instruction);
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
+static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
IrBasicBlock *old_dest_block = br_instruction->dest_block;
bool is_comptime;
- if (!ir_resolve_comptime(ira, br_instruction->is_comptime->other, &is_comptime))
+ if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime))
return ir_unreach_error(ira);
if (is_comptime || old_dest_block->ref_count == 1)
@@ -14179,17 +13880,19 @@ static ZigType *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_in
if (new_bb == nullptr)
return ir_unreach_error(ira);
- ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ IrInstruction *result = ir_build_br(&ira->new_irb,
+ br_instruction->base.scope, br_instruction->base.source_node, new_bb, nullptr);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
-static ZigType *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
- IrInstruction *condition = cond_br_instruction->condition->other;
+static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
+ IrInstruction *condition = cond_br_instruction->condition->child;
if (type_is_invalid(condition->value.type))
return ir_unreach_error(ira);
bool is_comptime;
- if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->other, &is_comptime))
+ if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
return ir_unreach_error(ira);
if (is_comptime || instr_is_comptime(condition)) {
@@ -14207,8 +13910,10 @@ static ZigType *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCond
if (new_dest_block == nullptr)
return ir_unreach_error(ira);
- ir_build_br_from(&ira->new_irb, &cond_br_instruction->base, new_dest_block);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ IrInstruction *result = ir_build_br(&ira->new_irb,
+ cond_br_instruction->base.scope, cond_br_instruction->base.source_node, new_dest_block, nullptr);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
@@ -14225,36 +13930,41 @@ static ZigType *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCond
if (new_else_block == nullptr)
return ir_unreach_error(ira);
- ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base,
+ IrInstruction *result = ir_build_cond_br(&ira->new_irb,
+ cond_br_instruction->base.scope, cond_br_instruction->base.source_node,
casted_condition, new_then_block, new_else_block, nullptr);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
-static ZigType *ir_analyze_instruction_unreachable(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_unreachable(IrAnalyze *ira,
IrInstructionUnreachable *unreachable_instruction)
{
- ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ IrInstruction *result = ir_build_unreachable(&ira->new_irb,
+ unreachable_instruction->base.scope, unreachable_instruction->base.source_node);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
-static ZigType *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
+static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
if (ira->const_predecessor_bb) {
for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i];
if (predecessor != ira->const_predecessor_bb)
continue;
- IrInstruction *value = phi_instruction->incoming_values[i]->other;
+ IrInstruction *value = phi_instruction->incoming_values[i]->child;
assert(value->value.type);
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (value->value.special != ConstValSpecialRuntime) {
- ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base);
- *out_val = value->value;
+ IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
+ // TODO use copy_const_val?
+ result->value = value->value;
+ return result;
} else {
- phi_instruction->base.other = value;
+ return value;
}
- return value->value.type;
}
zig_unreachable();
}
@@ -14270,12 +13980,12 @@ static ZigType *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi
IrInstruction *old_value = phi_instruction->incoming_values[i];
assert(old_value);
- IrInstruction *new_value = old_value->other;
+ IrInstruction *new_value = old_value->child;
if (!new_value || new_value->value.type->id == ZigTypeIdUnreachable || predecessor->other == nullptr)
continue;
if (type_is_invalid(new_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(predecessor->other);
@@ -14284,20 +13994,20 @@ static ZigType *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi
}
if (new_incoming_blocks.length == 0) {
- ir_build_unreachable_from(&ira->new_irb, &phi_instruction->base);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ IrInstruction *result = ir_build_unreachable(&ira->new_irb,
+ phi_instruction->base.scope, phi_instruction->base.source_node);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
if (new_incoming_blocks.length == 1) {
- IrInstruction *first_value = new_incoming_values.at(0);
- phi_instruction->base.other = first_value;
- return first_value->value.type;
+ return new_incoming_values.at(0);
}
ZigType *resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr,
new_incoming_values.items, new_incoming_values.length);
if (type_is_invalid(resolved_type))
- return resolved_type;
+ return ira->codegen->invalid_instruction;
if (resolved_type->id == ZigTypeIdComptimeFloat ||
resolved_type->id == ZigTypeIdComptimeInt ||
@@ -14306,7 +14016,7 @@ static ZigType *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi
{
ir_add_error_node(ira, phi_instruction->base.source_node,
buf_sprintf("unable to infer expression type"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
@@ -14322,7 +14032,7 @@ static ZigType *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi
ir_set_cursor_at_end(&ira->new_irb, predecessor);
IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);
if (casted_value == ira->codegen->invalid_instruction) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
new_incoming_values.items[i] = casted_value;
predecessor->instruction_list.append(branch_instruction);
@@ -14335,24 +14045,20 @@ static ZigType *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi
}
ir_set_cursor_at_end(&ira->new_irb, cur_bb);
- IrInstruction *result = ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,
- new_incoming_blocks.items, new_incoming_values.items);
+ IrInstruction *result = ir_build_phi(&ira->new_irb,
+ phi_instruction->base.scope, phi_instruction->base.source_node,
+ new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items);
+ result->value.type = resolved_type;
if (all_stack_ptrs) {
assert(result->value.special == ConstValSpecialRuntime);
result->value.data.rh_ptr = RuntimeHintPtrStack;
}
- return resolved_type;
+ return result;
}
-static ZigType *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
- IrInstruction *result = ir_get_var_ptr(ira, instruction, var);
- ir_link_new_instruction(result, instruction);
- return result->value.type;
-}
-
-static ZigType *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *instruction) {
+static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *instruction) {
ZigVar *var = instruction->var;
IrInstruction *result = ir_get_var_ptr(ira, &instruction->base, var);
if (instruction->crossed_fndef_scope != nullptr && !instr_is_comptime(result)) {
@@ -14362,10 +14068,9 @@ static ZigType *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarP
buf_sprintf("crossed function definition here"));
add_error_note(ira->codegen, msg, var->decl_node,
buf_sprintf("declared here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return result;
}
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {
@@ -14395,17 +14100,17 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
}
-static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
+static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
Error err;
- IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other;
+ IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->child;
if (type_is_invalid(array_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *orig_array_ptr_val = &array_ptr->value;
- IrInstruction *elem_index = elem_ptr_instruction->elem_index->other;
+ IrInstruction *elem_index = elem_ptr_instruction->elem_index->child;
if (type_is_invalid(elem_index->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = orig_array_ptr_val->type;
assert(ptr_type->id == ZigTypeIdPointer);
@@ -14417,7 +14122,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
ZigType *return_type;
if (type_is_invalid(array_type)) {
- return array_type;
+ return ira->codegen->invalid_instruction;
} else if (array_type->id == ZigTypeIdArray ||
(array_type->id == ZigTypeIdPointer &&
array_type->data.pointer.ptr_len == PtrLenSingle &&
@@ -14430,13 +14135,13 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
orig_array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,
elem_ptr_instruction->base.source_node);
if (orig_array_ptr_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
if (array_type->data.array.len == 0) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index 0 outside array of size 0"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *child_type = array_type->data.array.child_type;
if (ptr_type->data.pointer.host_int_bytes == 0) {
@@ -14447,7 +14152,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
} else {
uint64_t elem_val_scalar;
if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t bit_width = type_size_bits(ira->codegen, child_type);
size_t bit_offset = bit_width * elem_val_scalar;
@@ -14461,7 +14166,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
if (array_type->data.pointer.ptr_len == PtrLenSingle) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index of single-item pointer"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len);
} else if (is_slice(array_type)) {
@@ -14470,21 +14175,21 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
} else if (array_type->id == ZigTypeIdArgTuple) {
ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
if (!ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *args_val = ir_const_ptr_pointee(ira, ptr_val, elem_ptr_instruction->base.source_node);
if (args_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t start = args_val->data.x_arg_tuple.start_index;
size_t end = args_val->data.x_arg_tuple.end_index;
uint64_t elem_index_val;
if (!ir_resolve_usize(ira, elem_index, &elem_index_val))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t index = elem_index_val;
size_t len = end - start;
if (index >= len) {
ir_add_error(ira, &elem_ptr_instruction->base,
buf_sprintf("index %" ZIG_PRI_usize " outside argument list of size %" ZIG_PRI_usize "", index, len));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
size_t abs_index = start + index;
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
@@ -14493,25 +14198,25 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
bool is_const = true;
bool is_volatile = false;
if (var) {
- return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var);
+ return ir_get_var_ptr(ira, &elem_ptr_instruction->base, var);
} else {
- return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,
- ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile);
+ return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,
+ ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0);
}
} else {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *usize = ira->codegen->builtin_types.entry_usize;
IrInstruction *casted_elem_index = ir_implicit_cast(ira, elem_index, usize);
if (casted_elem_index == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool safety_check_on = elem_ptr_instruction->safety_check_on;
if ((err = ensure_complete_type(ira->codegen, return_type->data.pointer.child_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
@@ -14524,7 +14229,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,
index, array_len));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
safety_check_on = false;
}
@@ -14556,14 +14261,15 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
ConstExprValue *array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,
elem_ptr_instruction->base.source_node);
if (array_ptr_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != ZigTypeIdPointer ||
array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
{
if (array_type->id == ZigTypeIdPointer) {
- ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
+ IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
+ ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
size_t new_index;
size_t mem_size;
@@ -14608,26 +14314,26 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
if (new_index >= mem_size) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside pointer of size %" ZIG_PRI_usize "", index, old_size));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- return return_type;
+ return result;
} else if (is_slice(array_type)) {
ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
IrInstruction *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);
result->value.type = return_type;
- ir_link_new_instruction(result, &elem_ptr_instruction->base);
- return return_type;
+ return result;
}
ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
- ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
+ IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
+ ConstExprValue *out_val = &result->value;
uint64_t slice_len = bigint_as_unsigned(&len_field->data.x_bigint);
if (index >= slice_len) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
index, slice_len));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut;
switch (ptr_field->data.x_ptr.special) {
@@ -14658,14 +14364,15 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
case ConstPtrSpecialFunction:
zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
}
- return return_type;
+ return result;
} else if (array_type->id == ZigTypeIdArray) {
- ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
+ IrInstruction *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;
out_val->data.x_ptr.data.base_array.array_val = array_ptr_val;
out_val->data.x_ptr.data.base_array.elem_index = index;
- return return_type;
+ return result;
} else {
zig_unreachable();
}
@@ -14678,7 +14385,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
ir_add_error(ira, elem_index,
buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known",
buf_ptr(&return_type->data.pointer.child_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (ptr_align < abi_align) {
if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
@@ -14695,8 +14402,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
array_ptr, casted_elem_index, safety_check_on, elem_ptr_instruction->ptr_len);
result->value.type = return_type;
- ir_link_new_instruction(result, &elem_ptr_instruction->base);
- return return_type;
+ return result;
}
static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
@@ -14776,13 +14482,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
is_const, is_volatile, PtrLenSingle, align_bytes,
(uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
(uint32_t)host_int_bytes_for_result_type);
- IrInstruction *result = ir_get_const(ira, source_instr);
+ IrInstruction *result = ir_const(ira, source_instr, ptr_type);
ConstExprValue *const_val = &result->value;
const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
- const_val->type = ptr_type;
return result;
}
}
@@ -14840,12 +14545,11 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
is_const, is_volatile, PtrLenSingle, 0, 0, 0);
- IrInstruction *result = ir_get_const(ira, source_instr);
+ 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;
- const_val->type = ptr_type;
return result;
}
}
@@ -14882,11 +14586,11 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
}
-static ZigType *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
+static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
bool pointer_only = false;
resolve_top_level_decl(ira->codegen, tld, pointer_only, source_instruction->source_node);
if (tld->resolution == TldResolutionInvalid)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (tld->id) {
case TldIdContainer:
@@ -14900,7 +14604,7 @@ static ZigType *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instru
add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node);
}
- return ir_analyze_var_ptr(ira, source_instruction, var);
+ return ir_get_var_ptr(ira, source_instruction, var);
}
case TldIdFn:
{
@@ -14909,7 +14613,7 @@ static ZigType *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instru
assert(fn_entry->type_entry);
if (type_is_invalid(fn_entry->type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
// TODO instead of allocating this every time, put it in the tld value and we can reference
// the same one every time
@@ -14926,8 +14630,8 @@ static ZigType *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instru
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ return ir_get_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
}
}
zig_unreachable();
@@ -14944,45 +14648,43 @@ static ErrorTableEntry *find_err_table_entry(ZigType *err_set_type, Buf *field_n
return nullptr;
}
-static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) {
+static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) {
Error err;
- IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other;
+ IrInstruction *container_ptr = field_ptr_instruction->container_ptr->child;
if (type_is_invalid(container_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (container_ptr->value.type->id != ZigTypeIdPointer) {
ir_add_error_node(ira, field_ptr_instruction->base.source_node,
buf_sprintf("attempt to dereference non-pointer type '%s'",
buf_ptr(&container_ptr->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *container_type = container_ptr->value.type->data.pointer.child_type;
Buf *field_name = field_ptr_instruction->field_name_buffer;
if (!field_name) {
- IrInstruction *field_name_expr = field_ptr_instruction->field_name_expr->other;
+ IrInstruction *field_name_expr = field_ptr_instruction->field_name_expr->child;
field_name = ir_resolve_str(ira, field_name_expr);
if (!field_name)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
AstNode *source_node = field_ptr_instruction->base.source_node;
if (type_is_invalid(container_type)) {
- return container_type;
+ return ira->codegen->invalid_instruction;
} else if (is_container_ref(container_type)) {
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 *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type);
- ir_link_new_instruction(result, &field_ptr_instruction->base);
- return result->value.type;
+ return result;
} else {
IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type);
- ir_link_new_instruction(result, &field_ptr_instruction->base);
- return result->value.type;
+ return result;
}
} else if (is_array_ref(container_type)) {
if (buf_eql_str(field_name, "len")) {
@@ -14996,23 +14698,23 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
ZigType *usize = ira->codegen->builtin_types.entry_usize;
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
- usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base, len_val,
+ usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error_node(ira, source_node,
buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (container_type->id == ZigTypeIdArgTuple) {
ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
if (!container_ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(container_ptr->value.type->id == ZigTypeIdPointer);
ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);
if (child_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (buf_eql_str(field_name, "len")) {
ConstExprValue *len_val = create_const_vals(1);
@@ -15022,27 +14724,27 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
ZigType *usize = ira->codegen->builtin_types.entry_usize;
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
- usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base, len_val,
+ usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error_node(ira, source_node,
buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (container_type->id == ZigTypeIdMetaType) {
ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
if (!container_ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(container_ptr->value.type->id == ZigTypeIdPointer);
ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);
if (child_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *child_type = child_val->data.x_type;
if (type_is_invalid(child_type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (is_container(child_type)) {
if (is_slice(child_type) && buf_eql_str(field_name, "Child")) {
bool ptr_is_const = true;
@@ -15050,22 +14752,22 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
TypeStructField *ptr_field = &child_type->data.structure.fields[slice_ptr_index];
assert(ptr_field->type_entry->id == ZigTypeIdPointer);
ZigType *child_type = ptr_field->type_entry->data.pointer.child_type;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
}
if (child_type->id == ZigTypeIdEnum) {
if ((err = ensure_complete_type(ira->codegen, child_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
TypeEnumField *field = find_enum_type_field(child_type, field_name);
if (field) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_enum(child_type, &field->value), child_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
}
}
ScopeDecls *container_scope = get_container_scope(child_type);
@@ -15081,21 +14783,21 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
child_type->data.unionation.decl_node->data.container_decl.auto_enum))
{
if ((err = ensure_complete_type(ira->codegen, child_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
TypeUnionField *field = find_union_type_field(child_type, field_name);
if (field) {
ZigType *enum_type = child_type->data.unionation.tag_type;
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_enum(enum_type, &field->enum_field->value), enum_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
}
}
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("container '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (child_type->id == ZigTypeIdErrorSet) {
ErrorTableEntry *err_entry;
ZigType *err_set_type;
@@ -15123,13 +14825,13 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
err_set_type = err_entry->set_with_only_this_in_it;
} else {
if (!resolve_inferred_error_set(ira->codegen, child_type, field_ptr_instruction->base.source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
err_entry = find_err_table_entry(child_type, field_name);
if (err_entry == nullptr) {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("no error named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&child_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
err_set_type = child_type;
}
@@ -15140,128 +14842,128 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val,
- err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base, const_val,
+ err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (child_type->id == ZigTypeIdInt) {
if (buf_eql_str(field_name, "bit_count")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
child_type->data.integral.bit_count, false),
ira->codegen->builtin_types.entry_num_lit_int,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (buf_eql_str(field_name, "is_signed")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_bool(ira->codegen, child_type->data.integral.is_signed),
ira->codegen->builtin_types.entry_bool,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (child_type->id == ZigTypeIdFloat) {
if (buf_eql_str(field_name, "bit_count")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
child_type->data.floating.bit_count, false),
ira->codegen->builtin_types.entry_num_lit_int,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (child_type->id == ZigTypeIdPointer) {
if (buf_eql_str(field_name, "Child")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type->data.pointer.child_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (buf_eql_str(field_name, "alignment")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
if ((err = type_resolve(ira->codegen, child_type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
get_ptr_align(ira->codegen, child_type), false),
ira->codegen->builtin_types.entry_num_lit_int,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (child_type->id == ZigTypeIdArray) {
if (buf_eql_str(field_name, "Child")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type->data.array.child_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (buf_eql_str(field_name, "len")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
child_type->data.array.len, false),
ira->codegen->builtin_types.entry_num_lit_int,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (child_type->id == ZigTypeIdErrorUnion) {
if (buf_eql_str(field_name, "Payload")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type->data.error_union.payload_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (buf_eql_str(field_name, "ErrorSet")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type->data.error_union.err_set_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (child_type->id == ZigTypeIdOptional) {
if (buf_eql_str(field_name, "Child")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type->data.maybe.child_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (child_type->id == ZigTypeIdFn) {
if (buf_eql_str(field_name, "ReturnType")) {
@@ -15271,50 +14973,50 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("ReturnType has not been resolved because '%s' is generic", buf_ptr(&child_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_type(ira->codegen, child_type->data.fn.fn_type_id.return_type),
ira->codegen->builtin_types.entry_type,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (buf_eql_str(field_name, "is_var_args")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args),
ira->codegen->builtin_types.entry_bool,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else if (buf_eql_str(field_name, "arg_count")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
- return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
+ return ir_get_const_ptr(ira, &field_ptr_instruction->base,
create_const_usize(ira->codegen, child_type->data.fn.fn_type_id.param_count),
ira->codegen->builtin_types.entry_usize,
- ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
+ ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
ir_add_error(ira, &field_ptr_instruction->base,
buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else if (container_type->id == ZigTypeIdNamespace) {
assert(container_ptr->value.type->id == ZigTypeIdPointer);
ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
if (!container_ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *namespace_val = ir_const_ptr_pointee(ira, container_ptr_val,
field_ptr_instruction->base.source_node);
if (namespace_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(namespace_val->special == ConstValSpecialStatic);
ImportTableEntry *namespace_import = namespace_val->data.x_import;
@@ -15327,78 +15029,74 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
ErrorMsg *msg = ir_add_error_node(ira, source_node,
buf_sprintf("'%s' is private", buf_ptr(field_name)));
add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
return ir_analyze_decl_ref(ira, &field_ptr_instruction->base, tld);
} else {
const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";
ir_add_error_node(ira, source_node,
buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), import_name));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
ir_add_error_node(ira, field_ptr_instruction->base.source_node,
buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
- IrInstruction *ptr = load_ptr_instruction->ptr->other;
+static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
+ IrInstruction *ptr = load_ptr_instruction->ptr->child;
if (type_is_invalid(ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
-
- IrInstruction *result = ir_get_deref(ira, &load_ptr_instruction->base, ptr);
- ir_link_new_instruction(result, &load_ptr_instruction->base);
- assert(result->value.type);
- return result->value.type;
+ return ira->codegen->invalid_instruction;
+ return ir_get_deref(ira, &load_ptr_instruction->base, ptr);
}
-static ZigType *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
- IrInstruction *ptr = store_ptr_instruction->ptr->other;
+static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
+ IrInstruction *ptr = store_ptr_instruction->ptr->child;
if (type_is_invalid(ptr->value.type))
- return ptr->value.type;
+ return ira->codegen->invalid_instruction;
- IrInstruction *value = store_ptr_instruction->value->other;
+ IrInstruction *value = store_ptr_instruction->value->child;
if (type_is_invalid(value->value.type))
- return value->value.type;
+ return ira->codegen->invalid_instruction;
if (ptr->value.type->id != ZigTypeIdPointer) {
ir_add_error(ira, ptr,
buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
- return ir_analyze_void(ira, &store_ptr_instruction->base);
+ return ir_const_void(ira, &store_ptr_instruction->base);
}
if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) {
ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *child_type = ptr->value.type->data.pointer.child_type;
IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);
if (casted_value == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
if (instr_is_comptime(casted_value)) {
ConstExprValue *dest_val = ir_const_ptr_pointee(ira, &ptr->value, store_ptr_instruction->base.source_node);
if (dest_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_val->special != ConstValSpecialRuntime) {
*dest_val = casted_value->value;
if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
}
- return ir_analyze_void(ira, &store_ptr_instruction->base);
+ return ir_const_void(ira, &store_ptr_instruction->base);
}
}
ir_add_error(ira, &store_ptr_instruction->base,
@@ -15406,19 +15104,22 @@ static ZigType *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionSt
ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
dest_val->type = ira->codegen->builtin_types.entry_invalid;
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
- ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value);
- return ira->codegen->builtin_types.entry_void;
+ IrInstruction *result = ir_build_store_ptr(&ira->new_irb,
+ store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node,
+ ptr, casted_value);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
}
-static ZigType *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
- IrInstruction *expr_value = typeof_instruction->value->other;
+static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
+ IrInstruction *expr_value = typeof_instruction->value->child;
ZigType *type_entry = expr_value->value.type;
if (type_is_invalid(type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable(); // handled above
@@ -15446,24 +15147,19 @@ static ZigType *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeO
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
- {
- ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base);
- out_val->data.x_type = type_entry;
-
- return ira->codegen->builtin_types.entry_type;
- }
+ return ir_const_type(ira, &typeof_instruction->base, type_entry);
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
IrInstructionToPtrType *to_ptr_type_instruction)
{
- IrInstruction *value = to_ptr_type_instruction->value->other;
+ IrInstruction *value = to_ptr_type_instruction->value->child;
ZigType *type_entry = value->value.type;
if (type_is_invalid(type_entry))
- return type_entry;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type;
if (type_entry->id == ZigTypeIdArray) {
@@ -15473,76 +15169,69 @@ static ZigType *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
} else if (type_entry->id == ZigTypeIdArgTuple) {
ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
if (!arg_tuple_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &to_ptr_type_instruction->base);
- out_val->data.x_type = ptr_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &to_ptr_type_instruction->base, ptr_type);
}
-static ZigType *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
IrInstructionPtrTypeChild *ptr_type_child_instruction)
{
- IrInstruction *type_value = ptr_type_child_instruction->value->other;
+ 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 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &ptr_type_child_instruction->base);
- out_val->data.x_type = type_entry->data.pointer.child_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &ptr_type_child_instruction->base, type_entry->data.pointer.child_type);
}
-static ZigType *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) {
+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
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
- IrInstruction *is_cold_value = instruction->is_cold->other;
+ IrInstruction *is_cold_value = instruction->is_cold->child;
bool want_cold;
if (!ir_resolve_bool(ira, is_cold_value, &want_cold))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigFn *fn_entry = scope_fn_entry(instruction->base.scope);
if (fn_entry == nullptr) {
ir_add_error(ira, &instruction->base, buf_sprintf("@setCold outside function"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_entry->set_cold_node != nullptr) {
ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cold set twice in same function"));
add_error_note(ira->codegen, msg, fn_entry->set_cold_node, buf_sprintf("first set here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
fn_entry->set_cold_node = instruction->base.source_node;
fn_entry->is_cold = want_cold;
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
IrInstructionSetRuntimeSafety *set_runtime_safety_instruction)
{
if (ira->new_irb.exec->is_inline) {
// ignore setRuntimeSafety when running functions at compile time
- ir_build_const_from(ira, &set_runtime_safety_instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &set_runtime_safety_instruction->base);
}
bool *safety_off_ptr;
@@ -15574,32 +15263,30 @@ static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
}
assert(scope != nullptr);
- IrInstruction *safety_on_value = set_runtime_safety_instruction->safety_on->other;
+ IrInstruction *safety_on_value = set_runtime_safety_instruction->safety_on->child;
bool want_runtime_safety;
if (!ir_resolve_bool(ira, safety_on_value, &want_runtime_safety))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AstNode *source_node = set_runtime_safety_instruction->base.source_node;
if (*safety_set_node_ptr) {
ErrorMsg *msg = ir_add_error_node(ira, source_node,
buf_sprintf("runtime safety set twice for same scope"));
add_error_note(ira->codegen, msg, *safety_set_node_ptr, buf_sprintf("first set here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
*safety_set_node_ptr = source_node;
*safety_off_ptr = !want_runtime_safety;
- ir_build_const_from(ira, &set_runtime_safety_instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &set_runtime_safety_instruction->base);
}
-static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
IrInstructionSetFloatMode *instruction)
{
if (ira->new_irb.exec->is_inline) {
// ignore setFloatMode when running functions at compile time
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
bool *fast_math_on_ptr;
@@ -15631,38 +15318,37 @@ static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
}
assert(scope != nullptr);
- IrInstruction *float_mode_value = instruction->mode_value->other;
+ IrInstruction *float_mode_value = instruction->mode_value->child;
FloatMode float_mode_scalar;
if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AstNode *source_node = instruction->base.source_node;
if (*fast_math_set_node_ptr) {
ErrorMsg *msg = ir_add_error_node(ira, source_node,
buf_sprintf("float mode set twice for same scope"));
add_error_note(ira->codegen, msg, *fast_math_set_node_ptr, buf_sprintf("first set here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
*fast_math_set_node_ptr = source_node;
*fast_math_on_ptr = (float_mode_scalar == FloatModeOptimized);
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
IrInstructionSliceType *slice_type_instruction)
{
Error err;
uint32_t align_bytes = 0;
if (slice_type_instruction->align_value != nullptr) {
- if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_align(ira, slice_type_instruction->align_value->child, &align_bytes))
+ return ira->codegen->invalid_instruction;
}
- ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->other);
+ ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child);
if (type_is_invalid(child_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool is_const = slice_type_instruction->is_const;
bool is_volatile = slice_type_instruction->is_volatile;
@@ -15677,7 +15363,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdOpaque:
ir_add_error_node(ira, slice_type_instruction->base.source_node,
buf_sprintf("slice of type '%s' not allowed", buf_ptr(&child_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
@@ -15699,19 +15385,17 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdPromise:
{
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);
ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type);
- ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base);
- out_val->data.x_type = result_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &slice_type_instruction->base, result_type);
}
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) {
+static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) {
assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr);
AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;
@@ -15723,18 +15407,17 @@ static ZigType *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm
{
ir_add_error(ira, &asm_instruction->base,
buf_sprintf("global assembly cannot have inputs, outputs, or clobbers"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
buf_append_char(&ira->codegen->global_asm, '\n');
buf_append_buf(&ira->codegen->global_asm, asm_expr->asm_template);
- ir_build_const_from(ira, &asm_instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &asm_instruction->base);
}
if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
// TODO validate the output types and variable types
@@ -15745,38 +15428,41 @@ static ZigType *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm
for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
AsmOutput *asm_output = asm_expr->output_list.at(i);
if (asm_output->return_type) {
- output_types[i] = asm_instruction->output_types[i]->other;
+ output_types[i] = asm_instruction->output_types[i]->child;
return_type = ir_resolve_type(ira, output_types[i]);
if (type_is_invalid(return_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
- input_list[i] = asm_instruction->input_list[i]->other;
+ input_list[i] = asm_instruction->input_list[i]->child;
if (type_is_invalid(input_list[i]->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ir_build_asm_from(&ira->new_irb, &asm_instruction->base, input_list, output_types,
- asm_instruction->output_vars, asm_instruction->return_count, asm_instruction->has_side_effects);
- return return_type;
+ IrInstruction *result = ir_build_asm(&ira->new_irb,
+ asm_instruction->base.scope, asm_instruction->base.source_node,
+ input_list, output_types, asm_instruction->output_vars, asm_instruction->return_count,
+ asm_instruction->has_side_effects);
+ result->value.type = return_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
IrInstructionArrayType *array_type_instruction)
{
Error err;
- IrInstruction *size_value = array_type_instruction->size->other;
+ IrInstruction *size_value = array_type_instruction->size->child;
uint64_t size;
if (!ir_resolve_usize(ira, size_value, &size))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *child_type_value = array_type_instruction->child_type->other;
+ IrInstruction *child_type_value = array_type_instruction->child_type->child;
ZigType *child_type = ir_resolve_type(ira, child_type_value);
if (type_is_invalid(child_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (child_type->id) {
case ZigTypeIdInvalid: // handled above
zig_unreachable();
@@ -15787,7 +15473,7 @@ static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira,
case ZigTypeIdOpaque:
ir_add_error_node(ira, array_type_instruction->base.source_node,
buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
@@ -15809,43 +15495,39 @@ static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira,
case ZigTypeIdPromise:
{
if ((err = ensure_complete_type(ira->codegen, child_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *result_type = get_array_type(ira->codegen, child_type, size);
- ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base);
- out_val->data.x_type = result_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &array_type_instruction->base, result_type);
}
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_promise_type(IrAnalyze *ira, IrInstructionPromiseType *instruction) {
+static IrInstruction *ir_analyze_instruction_promise_type(IrAnalyze *ira, IrInstructionPromiseType *instruction) {
ZigType *promise_type;
if (instruction->payload_type == nullptr) {
promise_type = ira->codegen->builtin_types.entry_promise;
} else {
- ZigType *payload_type = ir_resolve_type(ira, instruction->payload_type->other);
+ ZigType *payload_type = ir_resolve_type(ira, instruction->payload_type->child);
if (type_is_invalid(payload_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
promise_type = get_promise_type(ira->codegen, payload_type);
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = promise_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, promise_type);
}
-static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
IrInstructionSizeOf *size_of_instruction)
{
Error err;
- IrInstruction *type_value = size_of_instruction->type_value->other;
+ IrInstruction *type_value = size_of_instruction->type_value->child;
ZigType *type_entry = ir_resolve_type(ira, type_value);
if ((err = ensure_complete_type(ira->codegen, type_entry)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (type_entry->id) {
case ZigTypeIdInvalid: // handled above
@@ -15862,7 +15544,7 @@ static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira,
case ZigTypeIdOpaque:
ir_add_error_node(ira, size_of_instruction->base.source_node,
buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
@@ -15879,18 +15561,16 @@ static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira,
case ZigTypeIdPromise:
{
uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
- ConstExprValue *out_val = ir_build_const_from(ira, &size_of_instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, size_in_bytes);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
}
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *type_entry = value->value.type;
@@ -15898,43 +15578,39 @@ static ZigType *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructi
if (instr_is_comptime(value)) {
ConstExprValue *maybe_val = ir_resolve_const(ira, value, UndefBad);
if (!maybe_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = !optional_value_is_null(maybe_val);
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val));
}
- ir_build_test_nonnull_from(&ira->new_irb, &instruction->base, value);
- return ira->codegen->builtin_types.entry_bool;
+ IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, value);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
} else if (type_entry->id == ZigTypeIdNull) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = false;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, false);
} else {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = true;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, true);
}
}
-static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
IrInstructionUnwrapOptional *unwrap_maybe_instruction)
{
- IrInstruction *value = unwrap_maybe_instruction->value->other;
+ IrInstruction *value = unwrap_maybe_instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = value->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *type_entry = ptr_type->data.pointer.child_type;
if (type_is_invalid(type_entry)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (type_entry->id != ZigTypeIdOptional) {
ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,
buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *child_type = type_entry->data.maybe.child_type;
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
@@ -15943,17 +15619,18 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *maybe_val = ir_const_ptr_pointee(ira, val, unwrap_maybe_instruction->base.source_node);
if (maybe_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
if (optional_value_is_null(maybe_val)) {
ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &unwrap_maybe_instruction->base);
+ IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);
+ ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.mut = val->data.x_ptr.mut;
if (type_is_codegen_pointer(child_type)) {
@@ -15961,83 +15638,87 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
} else {
out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
}
- return result_type;
+ return result;
}
}
- ir_build_unwrap_maybe_from(&ira->new_irb, &unwrap_maybe_instruction->base, value,
- unwrap_maybe_instruction->safety_check_on);
- return result_type;
+ IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,
+ unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,
+ value, unwrap_maybe_instruction->safety_check_on);
+ result->value.type = result_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
- IrInstruction *value = ctz_instruction->value->other;
+static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
+ IrInstruction *value = ctz_instruction->value->child;
if (type_is_invalid(value->value.type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (value->value.type->id == ZigTypeIdInt) {
ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen,
value->value.type->data.integral.bit_count);
if (value->value.special != ConstValSpecialRuntime) {
- size_t result = bigint_ctz(&value->value.data.x_bigint,
+ size_t result_usize = bigint_ctz(&value->value.data.x_bigint,
value->value.type->data.integral.bit_count);
- ConstExprValue *out_val = ir_build_const_from(ira, &ctz_instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, result);
- return return_type;
+ IrInstruction *result = ir_const(ira, &ctz_instruction->base, return_type);
+ bigint_init_unsigned(&result->value.data.x_bigint, result_usize);
+ return result;
}
- ir_build_ctz_from(&ira->new_irb, &ctz_instruction->base, value);
- return return_type;
+ IrInstruction *result = ir_build_ctz(&ira->new_irb,
+ ctz_instruction->base.scope, ctz_instruction->base.source_node, value);
+ result->value.type = return_type;
+ return result;
} else {
ir_add_error_node(ira, ctz_instruction->base.source_node,
buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *clz_instruction) {
- IrInstruction *value = clz_instruction->value->other;
+static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *clz_instruction) {
+ IrInstruction *value = clz_instruction->value->child;
if (type_is_invalid(value->value.type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (value->value.type->id == ZigTypeIdInt) {
ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen,
value->value.type->data.integral.bit_count);
if (value->value.special != ConstValSpecialRuntime) {
- size_t result = bigint_clz(&value->value.data.x_bigint,
+ size_t result_usize = bigint_clz(&value->value.data.x_bigint,
value->value.type->data.integral.bit_count);
- ConstExprValue *out_val = ir_build_const_from(ira, &clz_instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, result);
- return return_type;
+ IrInstruction *result = ir_const(ira, &clz_instruction->base, return_type);
+ bigint_init_unsigned(&result->value.data.x_bigint, result_usize);
+ return result;
}
- ir_build_clz_from(&ira->new_irb, &clz_instruction->base, value);
- return return_type;
+ IrInstruction *result = ir_build_clz(&ira->new_irb,
+ clz_instruction->base.scope, clz_instruction->base.source_node, value);
+ result->value.type = return_type;
+ return result;
} else {
ir_add_error_node(ira, clz_instruction->base.source_node,
buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (value->value.type->id != ZigTypeIdInt && value->value.type->id != ZigTypeIdComptimeInt) {
ir_add_error(ira, value,
buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) {
size_t result = bigint_popcount_unsigned(&val->data.x_bigint);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, result);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, result);
}
if (value->value.type->id == ZigTypeIdComptimeInt) {
Buf *val_buf = buf_alloc();
@@ -16045,19 +15726,16 @@ static ZigType *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPo
ir_add_error(ira, &instruction->base,
buf_sprintf("@popCount on negative %s value %s",
buf_ptr(&value->value.type->name), buf_ptr(val_buf)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
size_t result = bigint_popcount_signed(&val->data.x_bigint, value->value.type->data.integral.bit_count);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, result);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, result);
}
IrInstruction *result = ir_build_pop_count(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, value);
result->value.type = get_smallest_unsigned_int_type(ira->codegen, value->value.type->data.integral.bit_count);
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return result;
}
static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) {
@@ -16103,15 +15781,15 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source
return result;
}
-static ZigType *ir_analyze_instruction_switch_br(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira,
IrInstructionSwitchBr *switch_br_instruction)
{
- IrInstruction *target_value = switch_br_instruction->target_value->other;
+ IrInstruction *target_value = switch_br_instruction->target_value->child;
if (type_is_invalid(target_value->value.type))
return ir_unreach_error(ira);
if (switch_br_instruction->switch_prongs_void != nullptr) {
- if (type_is_invalid(switch_br_instruction->switch_prongs_void->other->value.type)) {
+ if (type_is_invalid(switch_br_instruction->switch_prongs_void->child->value.type)) {
return ir_unreach_error(ira);
}
}
@@ -16120,8 +15798,8 @@ static ZigType *ir_analyze_instruction_switch_br(IrAnalyze *ira,
size_t case_count = switch_br_instruction->case_count;
bool is_comptime;
- if (!ir_resolve_comptime(ira, switch_br_instruction->is_comptime->other, &is_comptime))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_comptime(ira, switch_br_instruction->is_comptime->child, &is_comptime))
+ return ira->codegen->invalid_instruction;
if (is_comptime || instr_is_comptime(target_value)) {
ConstExprValue *target_val = ir_resolve_const(ira, target_value, UndefBad);
@@ -16131,7 +15809,7 @@ static ZigType *ir_analyze_instruction_switch_br(IrAnalyze *ira,
IrBasicBlock *old_dest_block = switch_br_instruction->else_block;
for (size_t i = 0; i < case_count; i += 1) {
IrInstructionSwitchBrCase *old_case = &switch_br_instruction->cases[i];
- IrInstruction *case_value = old_case->value->other;
+ IrInstruction *case_value = old_case->value->child;
if (type_is_invalid(case_value->value.type))
return ir_unreach_error(ira);
@@ -16159,8 +15837,11 @@ static ZigType *ir_analyze_instruction_switch_br(IrAnalyze *ira,
return ir_inline_bb(ira, &switch_br_instruction->base, old_dest_block);
} else {
IrBasicBlock *new_dest_block = ir_get_new_bb(ira, old_dest_block, &switch_br_instruction->base);
- ir_build_br_from(&ira->new_irb, &switch_br_instruction->base, new_dest_block);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ IrInstruction *result = ir_build_br(&ira->new_irb,
+ switch_br_instruction->base.scope, switch_br_instruction->base.source_node,
+ new_dest_block, nullptr);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
}
@@ -16178,7 +15859,7 @@ static ZigType *ir_analyze_instruction_switch_br(IrAnalyze *ira,
new_case->block->ref_instruction = nullptr;
IrInstruction *old_value = old_case->value;
- IrInstruction *new_value = old_value->other;
+ IrInstruction *new_value = old_value->child;
if (type_is_invalid(new_value->value.type))
continue;
@@ -16206,32 +15887,31 @@ static ZigType *ir_analyze_instruction_switch_br(IrAnalyze *ira,
}
IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base);
- ir_build_switch_br_from(&ira->new_irb, &switch_br_instruction->base,
- target_value, new_else_block, case_count, cases, nullptr, nullptr);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ IrInstruction *result = ir_build_switch_br(&ira->new_irb,
+ switch_br_instruction->base.scope, switch_br_instruction->base.source_node,
+ target_value, new_else_block, case_count, cases, nullptr, nullptr);
+ result->value.type = ira->codegen->builtin_types.entry_unreachable;
+ return ir_finish_anal(ira, result);
}
-static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
IrInstructionSwitchTarget *switch_target_instruction)
{
Error err;
- IrInstruction *target_value_ptr = switch_target_instruction->target_value_ptr->other;
+ IrInstruction *target_value_ptr = switch_target_instruction->target_value_ptr->child;
if (type_is_invalid(target_value_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target_value_ptr->value.type->id == ZigTypeIdMetaType) {
assert(instr_is_comptime(target_value_ptr));
ZigType *ptr_type = target_value_ptr->value.data.x_type;
assert(ptr_type->id == ZigTypeIdPointer);
- ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
- out_val->type = ira->codegen->builtin_types.entry_type;
- out_val->data.x_type = ptr_type->data.pointer.child_type;
- return out_val->type;
+ return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type);
}
if (target_value_ptr->value.type->id != ZigTypeIdPointer) {
ir_add_error(ira, target_value_ptr, buf_sprintf("invalid deref on switch target"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
@@ -16239,13 +15919,13 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
if (instr_is_comptime(target_value_ptr)) {
pointee_val = ir_const_ptr_pointee(ira, &target_value_ptr->value, target_value_ptr->source_node);
if (pointee_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (pointee_val->special == ConstValSpecialRuntime)
pointee_val = nullptr;
}
if ((err = ensure_complete_type(ira->codegen, target_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (target_type->id) {
case ZigTypeIdInvalid:
@@ -16261,16 +15941,20 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case ZigTypeIdPromise:
case ZigTypeIdFn:
case ZigTypeIdNamespace:
- case ZigTypeIdErrorSet:
+ case ZigTypeIdErrorSet: {
if (pointee_val) {
- ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
- copy_const_val(out_val, pointee_val, true);
- out_val->type = target_type;
- return target_type;
+ IrInstruction *result = ir_const(ira, &switch_target_instruction->base, nullptr);
+ copy_const_val(&result->value, pointee_val, true);
+ result->value.type = target_type;
+ return result;
}
- ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr);
- return target_type;
+ IrInstruction *result = ir_build_load_ptr(&ira->new_irb,
+ switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
+ target_value_ptr);
+ result->value.type = target_type;
+ return result;
+ }
case ZigTypeIdUnion: {
AstNode *decl_node = target_type->data.unionation.decl_node;
if (!decl_node->data.container_decl.auto_enum &&
@@ -16280,21 +15964,21 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
buf_sprintf("switch on union which has no attached enum"));
add_error_note(ira->codegen, msg, decl_node,
buf_sprintf("consider 'union(enum)' here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *tag_type = target_type->data.unionation.tag_type;
assert(tag_type != nullptr);
assert(tag_type->id == ZigTypeIdEnum);
if (pointee_val) {
- ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
- bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag);
- return tag_type;
+ IrInstruction *result = ir_const(ira, &switch_target_instruction->base, tag_type);
+ bigint_init_bigint(&result->value.data.x_enum_tag, &pointee_val->data.x_union.tag);
+ return result;
}
if (tag_type->data.enumeration.src_field_count == 1) {
- ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
+ IrInstruction *result = ir_const(ira, &switch_target_instruction->base, tag_type);
TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
- bigint_init_bigint(&out_val->data.x_enum_tag, &only_field->value);
- return tag_type;
+ bigint_init_bigint(&result->value.data.x_enum_tag, &only_field->value);
+ return result;
}
IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
@@ -16304,30 +15988,28 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
switch_target_instruction->base.source_node, union_value);
union_tag_inst->value.type = tag_type;
- ir_link_new_instruction(union_tag_inst, &switch_target_instruction->base);
- return tag_type;
+ return union_tag_inst;
}
case ZigTypeIdEnum: {
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target_type->data.enumeration.src_field_count < 2) {
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
- ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
- bigint_init_bigint(&out_val->data.x_enum_tag, &only_field->value);
- return target_type;
+ IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type);
+ bigint_init_bigint(&result->value.data.x_enum_tag, &only_field->value);
+ return result;
}
if (pointee_val) {
- ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
- bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_enum_tag);
- return target_type;
+ IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type);
+ bigint_init_bigint(&result->value.data.x_enum_tag, &pointee_val->data.x_enum_tag);
+ return result;
}
IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
switch_target_instruction->base.source_node, target_value_ptr);
enum_value->value.type = target_type;
- ir_link_new_instruction(enum_value, &switch_target_instruction->base);
- return target_type;
+ return enum_value;
}
case ZigTypeIdErrorUnion:
case ZigTypeIdUnreachable:
@@ -16341,26 +16023,26 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case ZigTypeIdOpaque:
ir_add_error(ira, &switch_target_instruction->base,
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstructionSwitchVar *instruction) {
- IrInstruction *target_value_ptr = instruction->target_value_ptr->other;
+static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstructionSwitchVar *instruction) {
+ IrInstruction *target_value_ptr = instruction->target_value_ptr->child;
if (type_is_invalid(target_value_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *prong_value = instruction->prong_value->other;
+ IrInstruction *prong_value = instruction->prong_value->child;
if (type_is_invalid(prong_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(target_value_ptr->value.type->id == ZigTypeIdPointer);
ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
if (target_type->id == ZigTypeIdUnion) {
ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad);
if (!prong_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(prong_value->value.type->id == ZigTypeIdEnum);
TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag);
@@ -16368,43 +16050,46 @@ static ZigType *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstructionS
if (instr_is_comptime(target_value_ptr)) {
ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
if (!target_value_ptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, target_val_ptr, instruction->base.source_node);
if (pointee_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base,
+ get_pointer_to_type(ira->codegen, field->type_entry,
+ target_val_ptr->type->data.pointer.is_const));
+ ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut;
out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_union.payload;
- return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const);
+ return result;
}
- ir_build_union_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
- return get_pointer_to_type(ira->codegen, field->type_entry,
+ IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, target_value_ptr, field);
+ result->value.type = get_pointer_to_type(ira->codegen, field->type_entry,
target_value_ptr->value.type->data.pointer.is_const);
+ return result;
} else {
ir_add_error(ira, &instruction->base,
buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) {
- IrInstruction *value = instruction->value->other;
- IrInstruction *new_instruction = ir_analyze_union_tag(ira, &instruction->base, value);
- ir_link_new_instruction(new_instruction, &instruction->base);
- return new_instruction->value.type;
+static IrInstruction *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) {
+ IrInstruction *value = instruction->value->child;
+ return ir_analyze_union_tag(ira, &instruction->base, value);
}
-static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) {
+static IrInstruction *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) {
Error err;
- IrInstruction *name_value = import_instruction->name->other;
+ IrInstruction *name_value = import_instruction->name->child;
Buf *import_target_str = ir_resolve_str(ira, name_value);
if (!import_target_str)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AstNode *source_node = import_instruction->base.source_node;
ImportTableEntry *import = source_node->owner;
@@ -16439,20 +16124,21 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
auto import_entry = ira->codegen->import_table.maybe_get(resolved_path);
if (import_entry) {
- ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base);
- out_val->data.x_import = import_entry->value;
- return ira->codegen->builtin_types.entry_namespace;
+ IrInstruction *result = ir_const(ira, &import_instruction->base,
+ ira->codegen->builtin_types.entry_namespace);
+ result->value.data.x_import = import_entry->value;
+ return result;
}
if ((err = file_fetch(ira->codegen, resolved_path, import_code))) {
if (err == ErrorFileNotFound) {
ir_add_error_node(ira, source_node,
buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
ir_add_error_node(ira, source_node,
buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -16460,27 +16146,26 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
scan_import(ira->codegen, target_import);
- ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base);
- out_val->data.x_import = target_import;
- return ira->codegen->builtin_types.entry_namespace;
-
+ IrInstruction *result = ir_const(ira, &import_instruction->base, ira->codegen->builtin_types.entry_namespace);
+ result->value.data.x_import = target_import;
+ return result;
}
-static ZigType *ir_analyze_instruction_array_len(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_array_len(IrAnalyze *ira,
IrInstructionArrayLen *array_len_instruction)
{
- IrInstruction *array_value = array_len_instruction->array_value->other;
+ IrInstruction *array_value = array_len_instruction->array_value->child;
ZigType *type_entry = array_value->value.type;
if (type_is_invalid(type_entry)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (type_entry->id == ZigTypeIdArray) {
- return ir_analyze_const_usize(ira, &array_len_instruction->base,
+ return ir_const_usize(ira, &array_len_instruction->base,
type_entry->data.array.len);
} else if (is_slice(type_entry)) {
if (array_value->value.special != ConstValSpecialRuntime) {
ConstExprValue *len_val = &array_value->value.data.x_struct.fields[slice_len_index];
if (len_val->special != ConstValSpecialRuntime) {
- return ir_analyze_const_usize(ira, &array_len_instruction->base,
+ return ir_const_usize(ira, &array_len_instruction->base,
bigint_as_unsigned(&len_val->data.x_bigint));
}
}
@@ -16488,57 +16173,61 @@ static ZigType *ir_analyze_instruction_array_len(IrAnalyze *ira,
IrInstruction *len_ptr = ir_build_struct_field_ptr(&ira->new_irb, array_len_instruction->base.scope,
array_len_instruction->base.source_node, array_value, field);
len_ptr->value.type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_usize, true);
- ir_build_load_ptr_from(&ira->new_irb, &array_len_instruction->base, len_ptr);
- return ira->codegen->builtin_types.entry_usize;
+ IrInstruction *result = ir_build_load_ptr(&ira->new_irb,
+ array_len_instruction->base.scope, array_len_instruction->base.source_node, len_ptr);
+ result->value.type = ira->codegen->builtin_types.entry_usize;
+ return result;
} else {
ir_add_error_node(ira, array_len_instruction->base.source_node,
buf_sprintf("type '%s' has no field 'len'", buf_ptr(&array_value->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) {
- IrInstruction *value = ref_instruction->value->other;
- return ir_analyze_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile);
+static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) {
+ IrInstruction *value = ref_instruction->value->child;
+ if (type_is_invalid(value->value.type))
+ return ira->codegen->invalid_instruction;
+ return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile);
}
-static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
+static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
{
Error err;
assert(container_type->id == ZigTypeIdUnion);
if ((err = ensure_complete_type(ira->codegen, container_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstructionContainerInitFieldsField *field = &fields[0];
- IrInstruction *field_value = field->value->other;
+ IrInstruction *field_value = field->value->child;
if (type_is_invalid(field_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
TypeUnionField *type_field = find_union_type_field(container_type, field->name);
if (!type_field) {
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)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (type_is_invalid(type_field->type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
@@ -16546,9 +16235,10 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc
{
ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
if (!field_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, 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;
@@ -16558,17 +16248,18 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc
parent->data.p_union.union_val = out_val;
}
- return container_type;
+ return result;
}
- IrInstruction *new_instruction = ir_build_union_init_from(&ira->new_irb, instruction,
+ 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);
- return container_type;
+ return new_instruction;
}
-static ZigType *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
+static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
{
Error err;
@@ -16579,11 +16270,11 @@ static ZigType *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *
ir_add_error(ira, instruction,
buf_sprintf("type '%s' does not support struct initialization syntax",
buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if ((err = ensure_complete_type(ira->codegen, container_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t actual_field_count = container_type->data.structure.src_field_count;
@@ -16602,31 +16293,31 @@ static ZigType *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *
for (size_t i = 0; i < instr_field_count; i += 1) {
IrInstructionContainerInitFieldsField *field = &fields[i];
- IrInstruction *field_value = field->value->other;
+ IrInstruction *field_value = field->value->child;
if (type_is_invalid(field_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
TypeStructField *type_field = find_struct_type_field(container_type, field->name);
if (!type_field) {
ir_add_error_node(ira, field->source_node,
buf_sprintf("no member named '%s' in struct '%s'",
buf_ptr(field->name), buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (type_is_invalid(type_field->type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t field_index = type_field->src_index;
AstNode *existing_assign_node = field_assign_nodes[field_index];
if (existing_assign_node) {
ErrorMsg *msg = ir_add_error_node(ira, field->source_node, buf_sprintf("duplicate field"));
add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
field_assign_nodes[field_index] = field->source_node;
@@ -16637,7 +16328,7 @@ static ZigType *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *
if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
if (!field_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true);
} else {
@@ -16656,11 +16347,14 @@ static ZigType *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *
}
}
if (any_missing)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (const_val.special == ConstValSpecialStatic) {
- ConstExprValue *out_val = ir_build_const_from(ira, instruction);
+ IrInstruction *result = ir_const(ira, instruction, nullptr);
+ ConstExprValue *out_val = &result->value;
+ // TODO copy_const_val?
*out_val = const_val;
+ result->value.type = container_type;
for (size_t i = 0; i < instr_field_count; i += 1) {
ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
@@ -16672,34 +16366,35 @@ static ZigType *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *
}
}
- return container_type;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *new_instruction = ir_build_struct_init_from(&ira->new_irb, 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 container_type;
+ return new_instruction;
}
-static ZigType *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstructionContainerInitList *instruction)
{
- IrInstruction *container_type_value = instruction->container_type->other;
+ IrInstruction *container_type_value = instruction->container_type->child;
if (type_is_invalid(container_type_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t elem_count = instruction->item_count;
if (container_type_value->value.type->id == ZigTypeIdMetaType) {
ZigType *container_type = ir_resolve_type(ira, container_type_value);
if (type_is_invalid(container_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
@@ -16715,7 +16410,7 @@ static ZigType *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
@@ -16737,13 +16432,13 @@ static ZigType *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstruction *first_non_const_instruction = nullptr;
for (size_t i = 0; i < elem_count; i += 1) {
- IrInstruction *arg_value = instruction->items[i]->other;
+ IrInstruction *arg_value = instruction->items[i]->child;
if (type_is_invalid(arg_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
if (casted_arg == ira->codegen->invalid_instruction)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
new_items[i] = casted_arg;
@@ -16751,7 +16446,7 @@ static ZigType *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
if (!elem_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
} else {
@@ -16762,8 +16457,11 @@ static ZigType *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
}
if (const_val.special == ConstValSpecialStatic) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ ConstExprValue *out_val = &result->value;
+ // TODO copy_const_val?
*out_val = const_val;
+ 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);
@@ -16773,70 +16471,73 @@ static ZigType *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
parent->data.p_array.elem_index = i;
}
}
- return fixed_size_array_type;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *new_instruction = ir_build_container_init_list_from(&ira->new_irb, &instruction->base,
+ IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node,
container_type_value, elem_count, new_items);
+ new_instruction->value.type = fixed_size_array_type;
ir_add_alloca(ira, new_instruction, fixed_size_array_type);
- return fixed_size_array_type;
+ return new_instruction;
} 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- return ir_analyze_void(ira, &instruction->base);
+ 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)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
ir_add_error(ira, container_type_value,
buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {
- IrInstruction *container_type_value = instruction->container_type->other;
+static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {
+ IrInstruction *container_type_value = instruction->container_type->child;
ZigType *container_type = ir_resolve_type(ira, container_type_value);
if (type_is_invalid(container_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
instruction->field_count, instruction->fields);
}
-static ZigType *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruction,
+static IrInstruction *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruction,
IrInstruction *target_type_value, bool is_max)
{
ZigType *target_type = ir_resolve_type(ira, target_type_value);
if (type_is_invalid(target_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (target_type->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdInt:
{
- ConstExprValue *out_val = ir_build_const_from(ira, source_instruction);
- eval_min_max_value(ira->codegen, target_type, out_val, is_max);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ IrInstruction *result = ir_const(ira, source_instruction,
+ ira->codegen->builtin_types.entry_num_lit_int);
+ eval_min_max_value(ira->codegen, target_type, &result->value, is_max);
+ return result;
}
case ZigTypeIdBool:
case ZigTypeIdVoid:
{
- ConstExprValue *out_val = ir_build_const_from(ira, source_instruction);
- eval_min_max_value(ira->codegen, target_type, out_val, is_max);
- return target_type;
+ IrInstruction *result = ir_const(ira, source_instruction, target_type);
+ eval_min_max_value(ira->codegen, target_type, &result->value, is_max);
+ return result;
}
case ZigTypeIdEnum:
case ZigTypeIdFloat:
@@ -16865,31 +16566,31 @@ static ZigType *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruc
"no min value available for type '%s'";
ir_add_error(ira, source_instruction,
buf_sprintf(err_format, buf_ptr(&target_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_min_value(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_min_value(IrAnalyze *ira,
IrInstructionMinValue *instruction)
{
- return ir_analyze_min_max(ira, &instruction->base, instruction->value->other, false);
+ return ir_analyze_min_max(ira, &instruction->base, instruction->value->child, false);
}
-static ZigType *ir_analyze_instruction_max_value(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_max_value(IrAnalyze *ira,
IrInstructionMaxValue *instruction)
{
- return ir_analyze_min_max(ira, &instruction->base, instruction->value->other, true);
+ return ir_analyze_min_max(ira, &instruction->base, instruction->value->child, true);
}
-static ZigType *ir_analyze_instruction_compile_err(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
IrInstructionCompileErr *instruction)
{
- IrInstruction *msg_value = instruction->msg->other;
+ IrInstruction *msg_value = instruction->msg->child;
Buf *msg_buf = ir_resolve_str(ira, msg_value);
if (!msg_buf)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ErrorMsg *msg = ir_add_error(ira, &instruction->base, msg_buf);
size_t i = ira->codegen->tld_ref_source_node_stack.length;
@@ -16904,16 +16605,16 @@ static ZigType *ir_analyze_instruction_compile_err(IrAnalyze *ira,
}
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
-static ZigType *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstructionCompileLog *instruction) {
+static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstructionCompileLog *instruction) {
Buf buf = BUF_INIT;
fprintf(stderr, "| ");
for (size_t i = 0; i < instruction->msg_count; i += 1) {
- IrInstruction *msg = instruction->msg_list[i]->other;
+ IrInstruction *msg = instruction->msg_list[i]->child;
if (type_is_invalid(msg->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
buf_resize(&buf, 0);
render_const_value(ira->codegen, &buf, &msg->value);
const char *comma_str = (i != 0) ? ", " : "";
@@ -16925,18 +16626,17 @@ static ZigType *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstruction
// invalidate_exec to be called.
add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErrName *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErrName *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type);
if (type_is_invalid(casted_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown, 0, 0, 0);
@@ -16947,84 +16647,87 @@ static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErr
ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name);
err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- copy_const_val(out_val, err->cached_error_name_val, true);
- return str_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ copy_const_val(&result->value, err->cached_error_name_val, true);
+ result->value.type = str_type;
+ return result;
}
ira->codegen->generate_error_name_table = true;
- ir_build_err_name_from(&ira->new_irb, &instruction->base, value);
- return str_type;
+
+ IrInstruction *result = ir_build_err_name(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, value);
+ result->value.type = str_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionTagName *instruction) {
+static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionTagName *instruction) {
Error err;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(target->value.type->id == ZigTypeIdEnum);
if (instr_is_comptime(target)) {
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true);
- return out_val->type;
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true);
+ return result;
}
IrInstruction *result = ir_build_tag_name(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, target);
- ir_link_new_instruction(result, &instruction->base);
ZigType *u8_ptr_type = get_pointer_to_type_extra(
ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown,
0, 0, 0);
result->value.type = get_slice_type(ira->codegen, u8_ptr_type);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
IrInstructionFieldParentPtr *instruction)
{
Error err;
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
ZigType *container_type = ir_resolve_type(ira, type_value);
if (type_is_invalid(container_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *field_name_value = instruction->field_name->other;
+ IrInstruction *field_name_value = instruction->field_name->child;
Buf *field_name = ir_resolve_str(ira, field_name_value);
if (!field_name)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *field_ptr = instruction->field_ptr->other;
+ IrInstruction *field_ptr = instruction->field_ptr->child;
if (type_is_invalid(field_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (container_type->id != ZigTypeIdStruct) {
ir_add_error(ira, type_value,
buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if ((err = ensure_complete_type(ira->codegen, container_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
TypeStructField *field = find_struct_type_field(container_type, field_name);
if (field == nullptr) {
ir_add_error(ira, field_name_value,
buf_sprintf("struct '%s' has no field '%s'",
buf_ptr(&container_type->name), buf_ptr(field_name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (field_ptr->value.type->id != ZigTypeIdPointer) {
ir_add_error(ira, field_ptr,
buf_sprintf("expected pointer, found '%s'", buf_ptr(&field_ptr->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
bool is_packed = (container_type->data.structure.layout == ContainerLayoutPacked);
@@ -17038,7 +16741,7 @@ static ZigType *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
field_ptr_align, 0, 0);
IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type);
if (type_is_invalid(casted_field_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, container_type,
casted_field_ptr->value.type->data.pointer.is_const,
@@ -17049,11 +16752,11 @@ static ZigType *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
if (instr_is_comptime(casted_field_ptr)) {
ConstExprValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad);
if (!field_ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (field_ptr_val->data.x_ptr.special != ConstPtrSpecialBaseStruct) {
ir_add_error(ira, field_ptr, buf_sprintf("pointer value not based on parent struct"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
size_t ptr_field_index = field_ptr_val->data.x_ptr.data.base_struct.field_index;
@@ -17062,21 +16765,21 @@ static ZigType *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
buf_sprintf("field '%s' has index %" ZIG_PRI_usize " but pointer value is index %" ZIG_PRI_usize " of struct '%s'",
buf_ptr(field->name), field->src_index,
ptr_field_index, buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = field_ptr_val->data.x_ptr.data.base_struct.struct_val;
out_val->data.x_ptr.mut = field_ptr_val->data.x_ptr.mut;
-
- return result_type;
+ return result;
}
IrInstruction *result = ir_build_field_parent_ptr(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, type_value, field_name_value, casted_field_ptr, field);
- ir_link_new_instruction(result, &instruction->base);
- return result_type;
+ result->value.type = result_type;
+ return result;
}
static TypeStructField *validate_byte_offset(IrAnalyze *ira,
@@ -17121,44 +16824,39 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira,
return field;
}
-static ZigType *ir_analyze_instruction_byte_offset_of(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_byte_offset_of(IrAnalyze *ira,
IrInstructionByteOffsetOf *instruction)
{
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
if (type_is_invalid(type_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *field_name_value = instruction->field_name->other;
+ IrInstruction *field_name_value = instruction->field_name->child;
size_t byte_offset = 0;
if (!validate_byte_offset(ira, type_value, field_name_value, &byte_offset))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, byte_offset);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, byte_offset);
}
-static ZigType *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
IrInstructionBitOffsetOf *instruction)
{
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
if (type_is_invalid(type_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- IrInstruction *field_name_value = instruction->field_name->other;
+ return ira->codegen->invalid_instruction;
+ IrInstruction *field_name_value = instruction->field_name->child;
size_t byte_offset = 0;
TypeStructField *field = nullptr;
if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
size_t bit_offset = byte_offset * 8 + field->bit_offset_in_host;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, bit_offset);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, bit_offset);
}
-static void ensure_field_index(ZigType *type, const char *field_name, size_t index)
-{
+static void ensure_field_index(ZigType *type, const char *field_name, size_t index) {
Buf *field_name_buf;
assert(type != nullptr && !type_is_invalid(type));
@@ -17170,8 +16868,8 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
Error err;
- static ConstExprValue *type_info_var = nullptr;
- static ZigType *type_info_type = nullptr;
+ static ConstExprValue *type_info_var = nullptr; // TODO oops this global variable made it past code review
+ static ZigType *type_info_type = nullptr; // TODO oops this global variable made it past code review
if (type_info_var == nullptr) {
type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
assert(type_info_var->type->id == ZigTypeIdMetaType);
@@ -18080,23 +17778,23 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
return ErrorNone;
}
-static ZigType *ir_analyze_instruction_type_info(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
IrInstructionTypeInfo *instruction)
{
Error err;
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
ZigType *type_entry = ir_resolve_type(ira, type_value);
if (type_is_invalid(type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr);
ConstExprValue *payload;
if ((err = ir_make_type_info_value(ira, type_entry, &payload)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->type = result_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ ConstExprValue *out_val = &result->value;
bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry));
out_val->data.x_union.payload = payload;
@@ -18106,66 +17804,65 @@ static ZigType *ir_analyze_instruction_type_info(IrAnalyze *ira,
payload->data.x_struct.parent.data.p_union.union_val = out_val;
}
- return result_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_type_id(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
IrInstructionTypeId *instruction)
{
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
ZigType *type_entry = ir_resolve_type(ira, type_value);
if (type_is_invalid(type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeId");
assert(var_value->type->id == ZigTypeIdMetaType);
ZigType *result_type = var_value->data.x_type;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_enum_tag, type_id_index(type_entry));
- return result_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ bigint_init_unsigned(&result->value.data.x_enum_tag, type_id_index(type_entry));
+ return result;
}
-static ZigType *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
IrInstructionSetEvalBranchQuota *instruction)
{
if (ira->new_irb.exec->parent_exec != nullptr && !ira->new_irb.exec->is_generic_instantiation) {
ir_add_error(ira, &instruction->base,
buf_sprintf("@setEvalBranchQuota must be called from the top of the comptime stack"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
uint64_t new_quota;
- if (!ir_resolve_usize(ira, instruction->new_quota->other, &new_quota))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
+ return ira->codegen->invalid_instruction;
if (new_quota > ira->new_irb.exec->backward_branch_quota) {
ira->new_irb.exec->backward_branch_quota = new_quota;
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) {
- IrInstruction *type_value = instruction->type_value->other;
+static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) {
+ IrInstruction *type_value = instruction->type_value->child;
ZigType *type_entry = ir_resolve_type(ira, type_value);
if (type_is_invalid(type_entry))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (!type_entry->cached_const_name_val) {
type_entry->cached_const_name_val = create_const_str_lit(ira->codegen, &type_entry->name);
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- copy_const_val(out_val, type_entry->cached_const_name_val, true);
- return out_val->type;
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ copy_const_val(&result->value, type_entry->cached_const_name_val, true);
+ return result;
}
-static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
+static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
if (ira->codegen->enable_cache) {
ir_add_error(ira, &instruction->base,
buf_sprintf("TODO @cImport is incompatible with --cache on. The cache system currently is unable to detect subsequent changes in .h files."));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
AstNode *node = instruction->base.source_node;
@@ -18176,11 +17873,11 @@ static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCIm
// Execute the C import block like an inline function
ZigType *void_type = ira->codegen->builtin_types.entry_void;
- IrInstruction *result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
+ IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
&cimport_scope->buf, block_node, nullptr, nullptr);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ if (type_is_invalid(cimport_result->value.type))
+ return ira->codegen->invalid_instruction;
find_libc_include_path(ira->codegen);
@@ -18199,7 +17896,7 @@ static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCIm
if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) {
if (err != ErrorCCompileErrors) {
ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -18210,7 +17907,7 @@ static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCIm
err_msg_add_note(parent_err_msg, err_msg);
}
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (ira->codegen->verbose_cimport) {
@@ -18221,19 +17918,19 @@ static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCIm
scan_decls(ira->codegen, child_import->decls_scope, child_import->root);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_import = child_import;
- return ira->codegen->builtin_types.entry_namespace;
+ IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_namespace);
+ result->value.data.x_import = child_import;
+ return result;
}
-static ZigType *ir_analyze_instruction_c_include(IrAnalyze *ira, IrInstructionCInclude *instruction) {
- IrInstruction *name_value = instruction->name->other;
+static IrInstruction *ir_analyze_instruction_c_include(IrAnalyze *ira, IrInstructionCInclude *instruction) {
+ IrInstruction *name_value = instruction->name->child;
if (type_is_invalid(name_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *include_name = ir_resolve_str(ira, name_value);
if (!include_name)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec);
// We check for this error in pass1
@@ -18241,26 +17938,25 @@ static ZigType *ir_analyze_instruction_c_include(IrAnalyze *ira, IrInstructionCI
buf_appendf(c_import_buf, "#include <%s>\n", buf_ptr(include_name));
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstructionCDefine *instruction) {
- IrInstruction *name = instruction->name->other;
+static IrInstruction *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstructionCDefine *instruction) {
+ IrInstruction *name = instruction->name->child;
if (type_is_invalid(name->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *define_name = ir_resolve_str(ira, name);
if (!define_name)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *value = instruction->value->other;
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *define_value = ir_resolve_str(ira, value);
if (!define_value)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec);
// We check for this error in pass1
@@ -18268,18 +17964,17 @@ static ZigType *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstructionCDe
buf_appendf(c_import_buf, "#define %s %s\n", buf_ptr(define_name), buf_ptr(define_value));
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstructionCUndef *instruction) {
- IrInstruction *name = instruction->name->other;
+static IrInstruction *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstructionCUndef *instruction) {
+ IrInstruction *name = instruction->name->child;
if (type_is_invalid(name->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *undef_name = ir_resolve_str(ira, name);
if (!undef_name)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec);
// We check for this error in pass1
@@ -18287,18 +17982,17 @@ static ZigType *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstructionCUnd
buf_appendf(c_import_buf, "#undef %s\n", buf_ptr(undef_name));
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionEmbedFile *instruction) {
- IrInstruction *name = instruction->name->other;
+static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionEmbedFile *instruction) {
+ IrInstruction *name = instruction->name->child;
if (type_is_invalid(name->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
Buf *rel_file_path = ir_resolve_str(ira, name);
if (!rel_file_path)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ImportTableEntry *import = get_scope_import(instruction->base.scope);
// figure out absolute path to resource
@@ -18318,85 +18012,86 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
if ((err = file_fetch(ira->codegen, file_path, file_contents))) {
if (err == ErrorFileNotFound) {
ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(file_path)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- init_const_str_lit(ira->codegen, out_val, file_contents);
-
- return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(file_contents));
+ ZigType *result_type = get_array_type(ira->codegen,
+ ira->codegen->builtin_types.entry_u8, buf_len(file_contents));
+ IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ init_const_str_lit(ira->codegen, &result->value, file_contents);
+ return result;
}
-static ZigType *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->other);
+static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
if (type_is_invalid(operand_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *ptr = instruction->ptr->other;
+ IrInstruction *ptr = instruction->ptr->child;
if (type_is_invalid(ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
// 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);
if (type_is_invalid(casted_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *cmp_value = instruction->cmp_value->other;
+ IrInstruction *cmp_value = instruction->cmp_value->child;
if (type_is_invalid(cmp_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *new_value = instruction->new_value->other;
+ IrInstruction *new_value = instruction->new_value->child;
if (type_is_invalid(new_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *success_order_value = instruction->success_order_value->other;
+ IrInstruction *success_order_value = instruction->success_order_value->child;
if (type_is_invalid(success_order_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AtomicOrder success_order;
if (!ir_resolve_atomic_order(ira, success_order_value, &success_order))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *failure_order_value = instruction->failure_order_value->other;
+ IrInstruction *failure_order_value = instruction->failure_order_value->child;
if (type_is_invalid(failure_order_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AtomicOrder failure_order;
if (!ir_resolve_atomic_order(ira, failure_order_value, &failure_order))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_cmp_value = ir_implicit_cast(ira, cmp_value, operand_type);
if (type_is_invalid(casted_cmp_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_new_value = ir_implicit_cast(ira, new_value, operand_type);
if (type_is_invalid(casted_new_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (success_order < AtomicOrderMonotonic) {
ir_add_error(ira, success_order_value,
buf_sprintf("success atomic ordering must be Monotonic or stricter"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (failure_order < AtomicOrderMonotonic) {
ir_add_error(ira, failure_order_value,
buf_sprintf("failure atomic ordering must be Monotonic or stricter"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (failure_order > success_order) {
ir_add_error(ira, failure_order_value,
buf_sprintf("failure atomic ordering must be no stricter than success"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (failure_order == AtomicOrderRelease || failure_order == AtomicOrderAcqRel) {
ir_add_error(ira, failure_order_value,
buf_sprintf("failure atomic ordering must not be Release or AcqRel"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(casted_ptr) && instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
@@ -18407,127 +18102,118 @@ static ZigType *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpx
nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,
operand_type, success_order, failure_order);
result->value.type = get_optional_type(ira->codegen, operand_type);
- ir_link_new_instruction(result, &instruction->base);
ir_add_alloca(ira, result, result->value.type);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {
- IrInstruction *order_value = instruction->order_value->other;
+static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {
+ IrInstruction *order_value = instruction->order_value->child;
if (type_is_invalid(order_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AtomicOrder order;
if (!ir_resolve_atomic_order(ira, order_value, &order))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ir_build_fence_from(&ira->new_irb, &instruction->base, order_value, order);
- return ira->codegen->builtin_types.entry_void;
+ IrInstruction *result = ir_build_fence(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, order_value, order);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
}
-static ZigType *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstructionTruncate *instruction) {
- IrInstruction *dest_type_value = instruction->dest_type->other;
+static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstructionTruncate *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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_type->id != ZigTypeIdInt &&
dest_type->id != ZigTypeIdComptimeInt)
{
ir_add_error(ira, dest_type_value, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
ZigType *src_type = target->value.type;
if (type_is_invalid(src_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (src_type->id != ZigTypeIdInt &&
src_type->id != ZigTypeIdComptimeInt)
{
ir_add_error(ira, target, buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (src_type->data.integral.bit_count < dest_type->data.integral.bit_count) {
ir_add_error(ira, target, buf_sprintf("type '%s' has fewer bits than destination type '%s'",
buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (target->value.special == ConstValSpecialStatic) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_truncate(&out_val->data.x_bigint, &target->value.data.x_bigint, dest_type->data.integral.bit_count,
- dest_type->data.integral.is_signed);
- return dest_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
+ bigint_truncate(&result->value.data.x_bigint, &target->value.data.x_bigint,
+ dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
+ return result;
}
IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, dest_type_value, target);
- ir_link_new_instruction(new_instruction, &instruction->base);
- return dest_type;
+ new_instruction->value.type = dest_type;
+ return new_instruction;
}
-static ZigType *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstructionIntCast *instruction) {
- ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstructionIntCast *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_type->id != ZigTypeIdInt) {
ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id == ZigTypeIdComptimeInt) {
if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) {
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type,
- CastOpNumLitToConcrete, false);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpNumLitToConcrete, false);
} else {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
if (target->value.type->id != ZigTypeIdInt) {
ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",
buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
-
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
}
-static ZigType *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstructionFloatCast *instruction) {
- ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstructionFloatCast *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_type->id != ZigTypeIdFloat) {
ir_add_error(ira, instruction->dest_type,
buf_sprintf("expected float type, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id == ZigTypeIdComptimeInt ||
target->value.type->id == ZigTypeIdComptimeFloat)
@@ -18539,55 +18225,43 @@ static ZigType *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstructionF
} else {
op = CastOpNumLitToConcrete;
}
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, op, false);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, op, false);
} else {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
if (target->value.type->id != ZigTypeIdFloat) {
ir_add_error(ira, instruction->target, buf_sprintf("expected float type, found '%s'",
buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
}
-static ZigType *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructionErrSetCast *instruction) {
- ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructionErrSetCast *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_type->id != ZigTypeIdErrorSet) {
ir_add_error(ira, instruction->dest_type,
buf_sprintf("expected error set type, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id != ZigTypeIdErrorSet) {
ir_add_error(ira, instruction->target,
buf_sprintf("expected error set type, found '%s'", buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
}
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
@@ -18602,16 +18276,16 @@ static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_ali
return ErrorNone;
}
-static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
+static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
Error err;
- ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
+ ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->child);
if (type_is_invalid(dest_child_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool src_ptr_const;
bool src_ptr_volatile;
@@ -18621,26 +18295,26 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
src_ptr_volatile = target->value.type->data.pointer.is_volatile;
if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (is_slice(target->value.type)) {
ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
src_ptr_const = src_ptr_type->data.pointer.is_const;
src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
src_ptr_const = true;
src_ptr_volatile = false;
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusAlignmentKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
}
if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
src_ptr_const, src_ptr_volatile, PtrLenUnknown,
@@ -18654,7 +18328,7 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice);
if (type_is_invalid(casted_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool have_known_len = false;
uint64_t known_len;
@@ -18662,7 +18336,7 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
if (instr_is_comptime(casted_value)) {
ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
if (value_is_comptime(len_val)) {
@@ -18686,96 +18360,84 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
add_error_note(ira->codegen, msg, instruction->dest_child_type->source_node,
buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64,
buf_ptr(&dest_child_type->name), child_type_size, remainder));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true);
- ir_link_new_instruction(result, &instruction->base);
- return dest_slice_type;
+ return ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true);
}
-static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
+static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
Error err;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (!is_slice(target->value.type)) {
ir_add_error(ira, instruction->target,
buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
uint32_t alignment;
if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
alignment, 0, 0);
ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
- ir_link_new_instruction(result, &instruction->base);
- return dest_slice_type;
+ return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
}
-static ZigType *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
- ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) {
ir_add_error(ira, instruction->target, buf_sprintf("expected int type, found '%s'",
buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);
}
-static ZigType *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {
- ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id == ZigTypeIdComptimeInt) {
- IrInstruction *casted_value = ir_implicit_cast(ira, target, dest_type);
- if (type_is_invalid(casted_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- ir_link_new_instruction(casted_value, &instruction->base);
- return casted_value->value.type;
+ return ir_implicit_cast(ira, target, dest_type);
}
if (target->value.type->id != ZigTypeIdFloat && target->value.type->id != ZigTypeIdComptimeFloat) {
ir_add_error(ira, instruction->target, buf_sprintf("expected float type, found '%s'",
buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false);
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false);
}
-static ZigType *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
- IrInstruction *target = instruction->target->other;
+static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_target;
if (target->value.type->id == ZigTypeIdErrorSet) {
@@ -18783,110 +18445,100 @@ static ZigType *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionE
} else {
casted_target = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_global_error_set);
if (type_is_invalid(casted_target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_analyze_err_to_int(ira, &instruction->base, casted_target, ira->codegen->err_tag_type);
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return ir_analyze_err_to_int(ira, &instruction->base, casted_target, ira->codegen->err_tag_type);
}
-static ZigType *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstructionIntToErr *instruction) {
- IrInstruction *target = instruction->target->other;
+static IrInstruction *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstructionIntToErr *instruction) {
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type);
if (type_is_invalid(casted_target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_analyze_int_to_err(ira, &instruction->base, casted_target, ira->codegen->builtin_types.entry_global_error_set);
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return ir_analyze_int_to_err(ira, &instruction->base, casted_target, ira->codegen->builtin_types.entry_global_error_set);
}
-static ZigType *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
- IrInstruction *target = instruction->target->other;
+static IrInstruction *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id != ZigTypeIdBool) {
ir_add_error(ira, instruction->target, buf_sprintf("expected bool, found '%s'",
buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(target)) {
bool is_true;
if (!ir_resolve_bool(ira, target, &is_true))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, is_true ? 1 : 0);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, is_true ? 1 : 0);
}
ZigType *u1_type = get_int_type(ira->codegen, false, 1);
- IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);
- ir_link_new_instruction(result, &instruction->base);
- return u1_type;
+ return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);
}
-static ZigType *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
- IrInstruction *is_signed_value = instruction->is_signed->other;
+static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
+ IrInstruction *is_signed_value = instruction->is_signed->child;
bool is_signed;
if (!ir_resolve_bool(ira, is_signed_value, &is_signed))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *bit_count_value = instruction->bit_count->other;
+ IrInstruction *bit_count_value = instruction->bit_count->child;
uint64_t bit_count;
if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u32, &bit_count))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_int_type(ira->codegen, is_signed, (uint32_t)bit_count);
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
}
-static ZigType *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
IrInstruction *casted_value = ir_implicit_cast(ira, value, bool_type);
if (type_is_invalid(casted_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(casted_value)) {
ConstExprValue *value = ir_resolve_const(ira, casted_value, UndefBad);
if (value == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = !value->data.x_bool;
- return bool_type;
+ return ir_const_bool(ira, &instruction->base, !value->data.x_bool);
}
- ir_build_bool_not_from(&ira->new_irb, &instruction->base, casted_value);
- return bool_type;
+ IrInstruction *result = ir_build_bool_not(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, casted_value);
+ result->value.type = bool_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) {
+static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) {
Error err;
- IrInstruction *dest_ptr = instruction->dest_ptr->other;
+ IrInstruction *dest_ptr = instruction->dest_ptr->child;
if (type_is_invalid(dest_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *byte_value = instruction->byte->other;
+ IrInstruction *byte_value = instruction->byte->child;
if (type_is_invalid(byte_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *count_value = instruction->count->other;
+ IrInstruction *count_value = instruction->count->child;
if (type_is_invalid(count_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *dest_uncasted_type = dest_ptr->value.type;
bool dest_is_volatile = (dest_uncasted_type->id == ZigTypeIdPointer) &&
@@ -18897,7 +18549,7 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
uint32_t dest_align;
if (dest_uncasted_type->id == ZigTypeIdPointer) {
if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
dest_align = get_abi_alignment(ira->codegen, u8);
}
@@ -18906,15 +18558,15 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr);
if (type_is_invalid(casted_dest_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_byte = ir_implicit_cast(ira, byte_value, u8);
if (type_is_invalid(casted_byte->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_count = ir_implicit_cast(ira, count_value, usize);
if (type_is_invalid(casted_count->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
casted_byte->value.special == ConstValSpecialStatic &&
@@ -18956,7 +18608,7 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
size_t end = start + count;
if (end > bound_end) {
ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ConstExprValue *byte_val = &casted_byte->value;
@@ -18964,28 +18616,29 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
dest_elements[i] = *byte_val;
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
- ir_build_memset_from(&ira->new_irb, &instruction->base, casted_dest_ptr, casted_byte, casted_count);
- return ira->codegen->builtin_types.entry_void;
+ IrInstruction *result = ir_build_memset(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
+ casted_dest_ptr, casted_byte, casted_count);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
}
-static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) {
+static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) {
Error err;
- IrInstruction *dest_ptr = instruction->dest_ptr->other;
+ IrInstruction *dest_ptr = instruction->dest_ptr->child;
if (type_is_invalid(dest_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *src_ptr = instruction->src_ptr->other;
+ IrInstruction *src_ptr = instruction->src_ptr->child;
if (type_is_invalid(src_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *count_value = instruction->count->other;
+ IrInstruction *count_value = instruction->count->child;
if (type_is_invalid(count_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *u8 = ira->codegen->builtin_types.entry_u8;
ZigType *dest_uncasted_type = dest_ptr->value.type;
@@ -18998,7 +18651,7 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
uint32_t dest_align;
if (dest_uncasted_type->id == ZigTypeIdPointer) {
if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
dest_align = get_abi_alignment(ira->codegen, u8);
}
@@ -19006,7 +18659,7 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
uint32_t src_align;
if (src_uncasted_type->id == ZigTypeIdPointer) {
if ((err = resolve_ptr_align(ira, src_uncasted_type, &src_align)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
src_align = get_abi_alignment(ira->codegen, u8);
}
@@ -19019,15 +18672,15 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut);
if (type_is_invalid(casted_dest_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_src_ptr = ir_implicit_cast(ira, src_ptr, u8_ptr_const);
if (type_is_invalid(casted_src_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_count = ir_implicit_cast(ira, count_value, usize);
if (type_is_invalid(casted_count->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
casted_src_ptr->value.special == ConstValSpecialStatic &&
@@ -19068,7 +18721,7 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
if (dest_start + count > dest_end) {
ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ConstExprValue *src_ptr_val = &casted_src_ptr->value;
@@ -19104,7 +18757,7 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
if (src_start + count > src_end) {
ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
// TODO check for noalias violations - this should be generalized to work for any function
@@ -19113,40 +18766,41 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
dest_elements[dest_start + i] = src_elements[src_start + i];
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
- ir_build_memcpy_from(&ira->new_irb, &instruction->base, casted_dest_ptr, casted_src_ptr, casted_count);
- return ira->codegen->builtin_types.entry_void;
+ IrInstruction *result = ir_build_memcpy(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
+ casted_dest_ptr, casted_src_ptr, casted_count);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
}
-static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) {
- IrInstruction *ptr_ptr = instruction->ptr->other;
+static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) {
+ IrInstruction *ptr_ptr = instruction->ptr->child;
if (type_is_invalid(ptr_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = ptr_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *array_type = ptr_type->data.pointer.child_type;
- IrInstruction *start = instruction->start->other;
+ IrInstruction *start = instruction->start->child;
if (type_is_invalid(start->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *usize = ira->codegen->builtin_types.entry_usize;
IrInstruction *casted_start = ir_implicit_cast(ira, start, usize);
if (type_is_invalid(casted_start->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *end;
if (instruction->end) {
- end = instruction->end->other;
+ end = instruction->end->child;
if (type_is_invalid(end->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
end = ir_implicit_cast(ira, end, usize);
if (type_is_invalid(end->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
end = nullptr;
}
@@ -19174,13 +18828,13 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
return_type = get_slice_type(ira->codegen, slice_ptr_type);
} else {
ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
return_type = get_slice_type(ira->codegen, array_type);
if (!end) {
ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
} else if (is_slice(array_type)) {
@@ -19189,7 +18843,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
} else {
ir_add_error(ira, &instruction->base,
buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(ptr_ptr) &&
@@ -19209,18 +18863,18 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
assert(child_array_type->id == ZigTypeIdArray);
parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (parent_ptr == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
array_val = ir_const_ptr_pointee(ira, parent_ptr, instruction->base.source_node);
if (array_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
rel_end = child_array_type->data.array.len;
abs_offset = 0;
} else {
array_val = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (array_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
rel_end = array_type->data.array.len;
parent_ptr = nullptr;
abs_offset = 0;
@@ -19229,7 +18883,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (parent_ptr == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (parent_ptr->special == ConstValSpecialUndef) {
array_val = nullptr;
@@ -19269,12 +18923,12 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
} else if (is_slice(array_type)) {
ConstExprValue *slice_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (slice_ptr == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];
if (parent_ptr->special == ConstValSpecialUndef) {
ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index];
@@ -19310,7 +18964,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
uint64_t start_scalar = bigint_as_unsigned(&casted_start->value.data.x_bigint);
if (!ptr_is_undef && start_scalar > rel_end) {
ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
uint64_t end_scalar;
@@ -19322,19 +18976,20 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
if (!ptr_is_undef) {
if (end_scalar > rel_end) {
ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (start_scalar > end_scalar) {
ir_add_error(ira, &instruction->base, buf_sprintf("slice start is greater than end"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
if (ptr_is_undef && start_scalar != end_scalar) {
ir_add_error(ira, &instruction->base, buf_sprintf("non-zero length slice of undefined pointer"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base, return_type);
+ ConstExprValue *out_val = &result->value;
out_val->data.x_struct.fields = create_const_vals(2);
ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index];
@@ -19379,29 +19034,30 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
- return return_type;
+ return result;
}
- IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr_ptr,
- casted_start, end, instruction->safety_check_on);
+ 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 return_type;
+ return new_instruction;
}
-static ZigType *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {
+static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {
Error err;
- IrInstruction *container = instruction->container->other;
+ IrInstruction *container = instruction->container->child;
if (type_is_invalid(container->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *container_type = ir_resolve_type(ira, container);
if ((err = ensure_complete_type(ira->codegen, container_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
uint64_t result;
if (type_is_invalid(container_type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (container_type->id == ZigTypeIdEnum) {
result = container_type->data.enumeration.src_field_count;
} else if (container_type->id == ZigTypeIdStruct) {
@@ -19410,166 +19066,164 @@ static ZigType *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructio
result = container_type->data.unionation.src_field_count;
} else if (container_type->id == ZigTypeIdErrorSet) {
if (!resolve_inferred_error_set(ira->codegen, container_type, instruction->base.source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (type_is_global_error_set(container_type)) {
ir_add_error(ira, &instruction->base, buf_sprintf("global error set member count not available at comptime"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
result = container_type->data.error_set.err_count;
} else {
ir_add_error(ira, &instruction->base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, result);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, result);
}
-static ZigType *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstructionMemberType *instruction) {
+static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstructionMemberType *instruction) {
Error err;
- IrInstruction *container_type_value = instruction->container_type->other;
+ IrInstruction *container_type_value = instruction->container_type->child;
ZigType *container_type = ir_resolve_type(ira, container_type_value);
if (type_is_invalid(container_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = ensure_complete_type(ira->codegen, container_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
uint64_t member_index;
- IrInstruction *index_value = instruction->member_index->other;
+ IrInstruction *index_value = instruction->member_index->child;
if (!ir_resolve_usize(ira, index_value, &member_index))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (container_type->id == ZigTypeIdStruct) {
if (member_index >= container_type->data.structure.src_field_count) {
ir_add_error(ira, index_value,
buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
TypeStructField *field = &container_type->data.structure.fields[member_index];
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = field->type_entry;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, field->type_entry);
} else if (container_type->id == ZigTypeIdUnion) {
if (member_index >= container_type->data.unionation.src_field_count) {
ir_add_error(ira, index_value,
buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
TypeUnionField *field = &container_type->data.unionation.fields[member_index];
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = field->type_entry;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, field->type_entry);
} else {
ir_add_error(ira, container_type_value,
buf_sprintf("type '%s' does not support @memberType", buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstructionMemberName *instruction) {
+static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstructionMemberName *instruction) {
Error err;
- IrInstruction *container_type_value = instruction->container_type->other;
+ IrInstruction *container_type_value = instruction->container_type->child;
ZigType *container_type = ir_resolve_type(ira, container_type_value);
if (type_is_invalid(container_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = ensure_complete_type(ira->codegen, container_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
uint64_t member_index;
- IrInstruction *index_value = instruction->member_index->other;
+ IrInstruction *index_value = instruction->member_index->child;
if (!ir_resolve_usize(ira, index_value, &member_index))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (container_type->id == ZigTypeIdStruct) {
if (member_index >= container_type->data.structure.src_field_count) {
ir_add_error(ira, index_value,
buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
TypeStructField *field = &container_type->data.structure.fields[member_index];
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- init_const_str_lit(ira->codegen, out_val, field->name);
- return out_val->type;
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ init_const_str_lit(ira->codegen, &result->value, field->name);
+ return result;
} else if (container_type->id == ZigTypeIdEnum) {
if (member_index >= container_type->data.enumeration.src_field_count) {
ir_add_error(ira, index_value,
buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
TypeEnumField *field = &container_type->data.enumeration.fields[member_index];
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- init_const_str_lit(ira->codegen, out_val, field->name);
- return out_val->type;
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ init_const_str_lit(ira->codegen, &result->value, field->name);
+ return result;
} else if (container_type->id == ZigTypeIdUnion) {
if (member_index >= container_type->data.unionation.src_field_count) {
ir_add_error(ira, index_value,
buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
TypeUnionField *field = &container_type->data.unionation.fields[member_index];
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- init_const_str_lit(ira->codegen, out_val, field->name);
- return out_val->type;
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ init_const_str_lit(ira->codegen, &result->value, field->name);
+ return result;
} else {
ir_add_error(ira, container_type_value,
buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) {
- ir_build_breakpoint_from(&ira->new_irb, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+static IrInstruction *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) {
+ IrInstruction *result = ir_build_breakpoint(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
}
-static ZigType *ir_analyze_instruction_return_address(IrAnalyze *ira, IrInstructionReturnAddress *instruction) {
- ir_build_return_address_from(&ira->new_irb, &instruction->base);
-
+static IrInstruction *ir_analyze_instruction_return_address(IrAnalyze *ira, IrInstructionReturnAddress *instruction) {
+ IrInstruction *result = ir_build_return_address(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node);
ZigType *u8 = ira->codegen->builtin_types.entry_u8;
ZigType *u8_ptr_const = get_pointer_to_type(ira->codegen, u8, true);
- return u8_ptr_const;
+ result->value.type = u8_ptr_const;
+ return result;
}
-static ZigType *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstructionFrameAddress *instruction) {
- ir_build_frame_address_from(&ira->new_irb, &instruction->base);
-
+static IrInstruction *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstructionFrameAddress *instruction) {
+ IrInstruction *result = ir_build_frame_address(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node);
ZigType *u8 = ira->codegen->builtin_types.entry_u8;
ZigType *u8_ptr_const = get_pointer_to_type(ira->codegen, u8, true);
- return u8_ptr_const;
+ result->value.type = u8_ptr_const;
+ return result;
}
-static ZigType *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) {
- ir_build_handle_from(&ira->new_irb, &instruction->base);
-
+static IrInstruction *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) {
+ IrInstruction *result = ir_build_handle(&ira->new_irb, instruction->base.scope, instruction->base.source_node);
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
assert(fn_entry != nullptr);
- return get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
+ result->value.type = get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
+ return result;
}
-static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
+static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
Error err;
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
if (type_is_invalid(type_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *type_entry = ir_resolve_type(ira, type_value);
if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (type_entry->id) {
case ZigTypeIdInvalid:
@@ -19587,7 +19241,7 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
case ZigTypeIdOpaque:
ir_add_error(ira, instruction->type_value,
buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
case ZigTypeIdBool:
case ZigTypeIdInt:
case ZigTypeIdFloat:
@@ -19603,42 +19257,40 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
case ZigTypeIdFn:
{
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes);
- return ira->codegen->builtin_types.entry_num_lit_int;
+ return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
}
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
+static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
Error err;
- IrInstruction *type_value = instruction->type_value->other;
+ IrInstruction *type_value = instruction->type_value->child;
if (type_is_invalid(type_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *dest_type = ir_resolve_type(ira, type_value);
if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_type->id != ZigTypeIdInt) {
ir_add_error(ira, type_value,
buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *op1 = instruction->op1->other;
+ IrInstruction *op1 = instruction->op1->child;
if (type_is_invalid(op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type);
if (type_is_invalid(casted_op1->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op2 = instruction->op2->other;
+ IrInstruction *op2 = instruction->op2->child;
if (type_is_invalid(op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_op2;
if (instruction->op == IrOverflowOpShl) {
@@ -19649,17 +19301,17 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction
casted_op2 = ir_implicit_cast(ira, op2, dest_type);
}
if (type_is_invalid(casted_op2->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result_ptr = instruction->result_ptr->other;
+ IrInstruction *result_ptr = instruction->result_ptr->child;
if (type_is_invalid(result_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *expected_ptr_type;
if (result_ptr->value.type->id == ZigTypeIdPointer) {
uint32_t alignment;
if ((err = resolve_ptr_align(ira, result_ptr->value.type, &alignment)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
false, result_ptr->value.type->data.pointer.is_volatile,
PtrLenSingle,
@@ -19670,18 +19322,17 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction
IrInstruction *casted_result_ptr = ir_implicit_cast(ira, result_ptr, expected_ptr_type);
if (type_is_invalid(casted_result_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (casted_op1->value.special == ConstValSpecialStatic &&
casted_op2->value.special == ConstValSpecialStatic &&
casted_result_ptr->value.special == ConstValSpecialStatic)
{
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, &casted_result_ptr->value, casted_result_ptr->source_node);
if (pointee_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
BigInt *dest_bigint = &pointee_val->data.x_bigint;
switch (instruction->op) {
case IrOverflowOpAdd:
@@ -19697,77 +19348,74 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction
bigint_shl(dest_bigint, op1_bigint, op2_bigint);
break;
}
+ bool result_bool = false;
if (!bigint_fits_in_bits(dest_bigint, dest_type->data.integral.bit_count,
dest_type->data.integral.is_signed))
{
- out_val->data.x_bool = true;
+ result_bool = true;
BigInt tmp_bigint;
bigint_init_bigint(&tmp_bigint, dest_bigint);
bigint_truncate(dest_bigint, &tmp_bigint, dest_type->data.integral.bit_count,
dest_type->data.integral.is_signed);
}
pointee_val->special = ConstValSpecialStatic;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, result_bool);
}
- ir_build_overflow_op_from(&ira->new_irb, &instruction->base, instruction->op, type_value,
- casted_op1, casted_op2, casted_result_ptr, dest_type);
- return ira->codegen->builtin_types.entry_bool;
+ IrInstruction *result = ir_build_overflow_op(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node,
+ instruction->op, type_value, casted_op1, casted_op2, casted_result_ptr, dest_type);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+ return result;
}
-static ZigType *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *type_entry = value->value.type;
if (type_is_invalid(type_entry)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (type_entry->id == ZigTypeIdErrorUnion) {
if (instr_is_comptime(value)) {
ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
if (!err_union_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = (err_union_val->data.x_err_union.err != nullptr);
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr));
}
}
ZigType *err_set_type = type_entry->data.error_union.err_set_type;
if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (!type_is_global_error_set(err_set_type) &&
err_set_type->data.error_set.err_count == 0)
{
assert(err_set_type->data.error_set.infer_fn == nullptr);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = false;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, false);
}
- ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
- return ira->codegen->builtin_types.entry_bool;
+ 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;
} else if (type_entry->id == ZigTypeIdErrorSet) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = true;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, true);
} else {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = false;
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, false);
}
}
-static ZigType *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
IrInstructionUnwrapErrCode *instruction)
{
- IrInstruction *value = instruction->value->other;
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = value->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
@@ -19775,41 +19423,44 @@ static ZigType *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
ZigType *type_entry = ptr_type->data.pointer.child_type;
if (type_is_invalid(type_entry)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (type_entry->id == ZigTypeIdErrorUnion) {
if (instr_is_comptime(value)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
if (!ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
if (err_union_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.err;
assert(err);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_err_set = err;
- return type_entry->data.error_union.err_set_type;
+ IrInstruction *result = ir_const(ira, &instruction->base,
+ type_entry->data.error_union.err_set_type);
+ result->value.data.x_err_set = err;
+ return result;
}
}
- ir_build_unwrap_err_code_from(&ira->new_irb, &instruction->base, value);
- return type_entry->data.error_union.err_set_type;
+ IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, value);
+ result->value.type = type_entry->data.error_union.err_set_type;
+ return result;
} else {
ir_add_error(ira, value,
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
IrInstructionUnwrapErrPayload *instruction)
{
- assert(instruction->value->other);
- IrInstruction *value = instruction->value->other;
+ assert(instruction->value->child);
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = value->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
@@ -19817,11 +19468,11 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
ZigType *type_entry = ptr_type->data.pointer.child_type;
if (type_is_invalid(type_entry)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (type_entry->id == ZigTypeIdErrorUnion) {
ZigType *payload_type = type_entry->data.error_union.payload_type;
if (type_is_invalid(payload_type)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
@@ -19829,36 +19480,38 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
if (instr_is_comptime(value)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
if (!ptr_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
if (err_union_val == nullptr)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.err;
if (err != nullptr) {
ir_add_error(ira, &instruction->base,
buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_ptr.special = ConstPtrSpecialRef;
- out_val->data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
- return result_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ result->value.data.x_ptr.special = ConstPtrSpecialRef;
+ result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
+ return result;
}
}
- ir_build_unwrap_err_payload_from(&ira->new_irb, &instruction->base, value, instruction->safety_check_on);
- return result_type;
+ IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
+ result->value.type = result_type;
+ return result;
} else {
ir_add_error(ira, value,
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
+static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
Error err;
AstNode *proto_node = instruction->base.source_node;
assert(proto_node->type == NodeTypeFnProto);
@@ -19866,7 +19519,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
if (proto_node->data.fn_proto.auto_err_set) {
ir_add_error(ira, &instruction->base,
buf_sprintf("inferring error set of return type valid only for function definitions"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
FnTypeId fn_type_id = {0};
@@ -19882,9 +19535,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
fn_type_id.param_count = fn_type_id.next_param_index;
continue;
} else if (fn_type_id.cc == CallingConventionUnspecified) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id);
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
} else {
zig_unreachable();
}
@@ -19894,36 +19545,32 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
if (instruction->param_types[fn_type_id.next_param_index] == nullptr) {
param_info->type = nullptr;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id);
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
} else {
- IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other;
+ IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child;
if (type_is_invalid(param_type_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *param_type = ir_resolve_type(ira, param_type_value);
if (type_is_invalid(param_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (type_requires_comptime(param_type)) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
ir_add_error(ira, param_type_value,
buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
param_info->type = param_type;
fn_type_id.next_param_index += 1;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id);
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
}
if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
ir_add_error(ira, param_type_value,
buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
param_info->type = param_type;
}
@@ -19931,54 +19578,50 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
}
if (instruction->align_value != nullptr) {
- if (!ir_resolve_align(ira, instruction->align_value->other, &fn_type_id.alignment))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment))
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *return_type_value = instruction->return_type->other;
+ IrInstruction *return_type_value = instruction->return_type->child;
fn_type_id.return_type = ir_resolve_type(ira, return_type_value);
if (type_is_invalid(fn_type_id.return_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
ir_add_error(ira, instruction->return_type,
buf_sprintf("return type cannot be opaque"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_type_id.cc == CallingConventionAsync) {
if (instruction->async_allocator_type_value == nullptr) {
ir_add_error(ira, &instruction->base,
buf_sprintf("async fn proto missing allocator type"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->other;
+ IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->child;
fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value);
if (type_is_invalid(fn_type_id.async_allocator_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_fn_type(ira->codegen, &fn_type_id);
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));
}
-static ZigType *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
- IrInstruction *value = instruction->value->other;
+static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_bool = instr_is_comptime(value);
- return ira->codegen->builtin_types.entry_bool;
+ return ir_const_bool(ira, &instruction->base, instr_is_comptime(value));
}
-static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
IrInstructionCheckSwitchProngs *instruction)
{
- IrInstruction *target_value = instruction->target_value->other;
+ IrInstruction *target_value = instruction->target_value->child;
ZigType *switch_type = target_value->value.type;
if (type_is_invalid(switch_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (switch_type->id == ZigTypeIdEnum) {
HashMap field_prev_uses = {};
@@ -19987,17 +19630,17 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
- IrInstruction *start_value = range->start->other;
+ IrInstruction *start_value = range->start->child;
if (type_is_invalid(start_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *end_value = range->end->other;
+ IrInstruction *end_value = range->end->child;
if (type_is_invalid(end_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (start_value->value.type->id != ZigTypeIdEnum) {
ir_add_error(ira, range->start, buf_sprintf("not an enum type"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
BigInt start_index;
@@ -20041,7 +19684,7 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
}
} else if (switch_type->id == ZigTypeIdErrorSet) {
if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
AstNode **field_prev_uses = allocate(ira->codegen->errors_by_index.length);
@@ -20049,13 +19692,13 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
- IrInstruction *start_value = range->start->other;
+ IrInstruction *start_value = range->start->child;
if (type_is_invalid(start_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *end_value = range->end->other;
+ IrInstruction *end_value = range->end->child;
if (type_is_invalid(end_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(start_value->value.type->id == ZigTypeIdErrorSet);
uint32_t start_index = start_value->value.data.x_err_set->value;
@@ -20065,7 +19708,7 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
if (start_index != end_index) {
ir_add_error(ira, end_value, buf_sprintf("ranges not allowed when switching on errors"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
AstNode *prev_node = field_prev_uses[start_index];
@@ -20081,7 +19724,7 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
if (type_is_global_error_set(switch_type)) {
ir_add_error(ira, &instruction->base,
buf_sprintf("else prong required when switching on type 'error'"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) {
ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i];
@@ -20101,27 +19744,27 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
- IrInstruction *start_value = range->start->other;
+ IrInstruction *start_value = range->start->child;
if (type_is_invalid(start_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_start_value = ir_implicit_cast(ira, start_value, switch_type);
if (type_is_invalid(casted_start_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *end_value = range->end->other;
+ IrInstruction *end_value = range->end->child;
if (type_is_invalid(end_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_end_value = ir_implicit_cast(ira, end_value, switch_type);
if (type_is_invalid(casted_end_value->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *start_val = ir_resolve_const(ira, casted_start_value, UndefBad);
if (!start_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ConstExprValue *end_val = ir_resolve_const(ira, casted_end_value, UndefBad);
if (!end_val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(start_val->type->id == ZigTypeIdInt || start_val->type->id == ZigTypeIdComptimeInt);
assert(end_val->type->id == ZigTypeIdInt || end_val->type->id == ZigTypeIdComptimeInt);
@@ -20130,7 +19773,7 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
if (prev_node != nullptr) {
ErrorMsg *msg = ir_add_error(ira, start_value, buf_sprintf("duplicate switch value"));
add_error_note(ira->codegen, msg, prev_node, buf_sprintf("previous value is here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
if (!instruction->have_else_prong) {
@@ -20140,36 +19783,34 @@ static ZigType *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
eval_min_max_value_int(ira->codegen, switch_type, &max_val, true);
if (!rangeset_spans(&rs, &min_val, &max_val)) {
ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
} else if (!instruction->have_else_prong) {
ir_add_error(ira, &instruction->base,
buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_check_statement_is_void(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_check_statement_is_void(IrAnalyze *ira,
IrInstructionCheckStatementIsVoid *instruction)
{
- IrInstruction *statement_value = instruction->statement_value->other;
+ IrInstruction *statement_value = instruction->statement_value->child;
ZigType *statement_type = statement_value->value.type;
if (type_is_invalid(statement_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (statement_type->id != ZigTypeIdVoid) {
ir_add_error(ira, &instruction->base, buf_sprintf("expression value is ignored"));
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic *instruction) {
- IrInstruction *msg = instruction->msg->other;
+static IrInstruction *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic *instruction) {
+ IrInstruction *msg = instruction->msg->child;
if (type_is_invalid(msg->value.type))
return ir_unreach_error(ira);
@@ -20187,8 +19828,7 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
IrInstruction *new_instruction = ir_build_panic(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, casted_msg);
- ir_link_new_instruction(new_instruction, &instruction->base);
- return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
+ return ir_finish_anal(ira, new_instruction);
}
static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) {
@@ -20352,23 +19992,18 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
return result;
}
-static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
- IrInstruction *dest_type_value = instruction->dest_type->other;
+static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *ptr = instruction->ptr->other;
+ IrInstruction *ptr = instruction->ptr->child;
ZigType *src_type = ptr->value.type;
if (type_is_invalid(src_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
- if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
-
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
}
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
@@ -20498,28 +20133,28 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
+static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
Error err;
- IrInstruction *dest_type_value = instruction->dest_type->other;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *value = instruction->value->other;
+ IrInstruction *value = instruction->value->child;
ZigType *src_type = value->value.type;
if (type_is_invalid(src_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = ensure_complete_type(ira->codegen, dest_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if ((err = ensure_complete_type(ira->codegen, src_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
switch (src_type->id) {
@@ -20536,7 +20171,7 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
case ZigTypeIdNull:
ir_add_error(ira, dest_type_value,
buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
default:
break;
}
@@ -20544,7 +20179,7 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
switch (dest_type->id) {
@@ -20561,7 +20196,7 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
case ZigTypeIdNull:
ir_add_error(ira, dest_type_value,
buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
default:
break;
}
@@ -20573,76 +20208,74 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
buf_ptr(&dest_type->name), dest_size_bytes,
buf_ptr(&src_type->name), src_size_bytes));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->type = dest_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
uint8_t *buf = allocate_nonzero(src_size_bytes);
buf_write_value_bytes(ira->codegen, buf, val);
- buf_read_value_bytes(ira->codegen, buf, out_val);
- return dest_type;
+ buf_read_value_bytes(ira->codegen, buf, &result->value);
+ return result;
}
IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, value);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = dest_type;
- return dest_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
+static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
Error err;
- IrInstruction *dest_type_value = instruction->dest_type->other;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
// We explicitly check for the size, so we can use get_src_ptr_type
if (get_src_ptr_type(dest_type) == nullptr) {
ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (!type_has_bits(dest_type)) {
ir_add_error(ira, dest_type_value,
buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
if (type_is_invalid(casted_int->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(casted_int)) {
ConstExprValue *val = ir_resolve_const(ira, casted_int, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
- out_val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
- return dest_type;
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
+ result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
+ return result;
}
IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, casted_int);
- ir_link_new_instruction(result, &instruction->base);
- return dest_type;
+ result->value.type = dest_type;
+ return result;
}
-static ZigType *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
IrInstructionDeclRef *instruction)
{
Tld *tld = instruction->tld;
@@ -20650,7 +20283,7 @@ static ZigType *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
resolve_top_level_decl(ira->codegen, tld, lval == LValPtr, instruction->base.source_node);
if (tld->resolution == TldResolutionInvalid)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
switch (tld->id) {
case TldIdContainer:
@@ -20663,19 +20296,16 @@ static ZigType *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
IrInstruction *var_ptr = ir_get_var_ptr(ira, &instruction->base, var);
if (type_is_invalid(var_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (tld_var->extern_lib_name != nullptr) {
add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, instruction->base.source_node);
}
if (lval == LValPtr) {
- ir_link_new_instruction(var_ptr, &instruction->base);
- return var_ptr->value.type;
+ return var_ptr;
} else {
- IrInstruction *loaded_instr = ir_get_deref(ira, &instruction->base, var_ptr);
- ir_link_new_instruction(loaded_instr, &instruction->base);
- return loaded_instr->value.type;
+ return ir_get_deref(ira, &instruction->base, var_ptr);
}
}
case TldIdFn:
@@ -20691,22 +20321,19 @@ static ZigType *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, fn_entry);
if (lval == LValPtr) {
- IrInstruction *ptr_instr = ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
- ir_link_new_instruction(ptr_instr, &instruction->base);
- return ptr_instr->value.type;
+ return ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
} else {
- ir_link_new_instruction(ref_instruction, &instruction->base);
- return ref_instruction->value.type;
+ return ref_instruction;
}
}
}
zig_unreachable();
}
-static ZigType *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) {
- IrInstruction *target = instruction->target->other;
+static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) {
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *usize = ira->codegen->builtin_types.entry_usize;
@@ -20714,151 +20341,144 @@ static ZigType *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionP
if (get_src_ptr_type(target->value.type) == nullptr) {
ir_add_error(ira, target,
buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (!type_has_bits(target->value.type)) {
ir_add_error(ira, target,
buf_sprintf("pointer to size 0 type has no address"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(target)) {
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, usize);
bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
- ir_link_new_instruction(result, &instruction->base);
- return usize;
+ result->value.type = usize;
+ return result;
}
}
IrInstruction *result = ir_build_ptr_to_int(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, target);
result->value.type = usize;
- ir_link_new_instruction(result, &instruction->base);
- return usize;
+ return result;
}
-static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) {
+static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) {
Error err;
- ZigType *child_type = ir_resolve_type(ira, instruction->child_type->other);
+ ZigType *child_type = ir_resolve_type(ira, instruction->child_type->child);
if (type_is_invalid(child_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (child_type->id == ZigTypeIdUnreachable) {
ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
uint32_t align_bytes;
if (instruction->align_value != nullptr) {
- if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_align(ira, instruction->align_value->child, &align_bytes))
+ return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
} else {
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
align_bytes = 0;
}
-
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,
+ ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
instruction->is_const, instruction->is_volatile,
instruction->ptr_len, align_bytes,
instruction->bit_offset_start, instruction->host_int_bytes);
-
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, result_type);
}
-static ZigType *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {
+static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {
uint32_t align_bytes;
- IrInstruction *align_bytes_inst = instruction->align_bytes->other;
+ IrInstruction *align_bytes_inst = instruction->align_bytes->child;
if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_align_cast(ira, target, align_bytes, true);
if (type_is_invalid(result->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstructionOpaqueType *instruction) {
+static IrInstruction *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstructionOpaqueType *instruction) {
Buf *name = get_anon_type_name(ira->codegen, ira->new_irb.exec, "opaque", instruction->base.source_node);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = get_opaque_type(ira->codegen, instruction->base.scope, instruction->base.source_node,
+ ZigType *result_type = get_opaque_type(ira->codegen, instruction->base.scope, instruction->base.source_node,
buf_ptr(name));
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, result_type);
}
-static ZigType *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstructionSetAlignStack *instruction) {
+static IrInstruction *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstructionSetAlignStack *instruction) {
uint32_t align_bytes;
- IrInstruction *align_bytes_inst = instruction->align_bytes->other;
+ IrInstruction *align_bytes_inst = instruction->align_bytes->child;
if (!ir_resolve_align(ira, align_bytes_inst, &align_bytes))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (align_bytes > 256) {
ir_add_error(ira, &instruction->base, buf_sprintf("attempt to @setAlignStack(%" PRIu32 "); maximum is 256", align_bytes));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
if (fn_entry == nullptr) {
ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack outside function"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionNaked) {
ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack in naked function"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_entry->fn_inline == FnInlineAlways) {
ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack in inline function"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (fn_entry->set_alignstack_node != nullptr) {
ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node,
buf_sprintf("alignstack set twice"));
add_error_note(ira->codegen, msg, fn_entry->set_alignstack_node, buf_sprintf("first set here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
fn_entry->set_alignstack_node = instruction->base.source_node;
fn_entry->alignstack_value = align_bytes;
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstructionArgType *instruction) {
- IrInstruction *fn_type_inst = instruction->fn_type->other;
+static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstructionArgType *instruction) {
+ IrInstruction *fn_type_inst = instruction->fn_type->child;
ZigType *fn_type = ir_resolve_type(ira, fn_type_inst);
if (type_is_invalid(fn_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *arg_index_inst = instruction->arg_index->other;
+ IrInstruction *arg_index_inst = instruction->arg_index->child;
uint64_t arg_index;
if (!ir_resolve_usize(ira, arg_index_inst, &arg_index))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (fn_type->id != ZigTypeIdFn) {
ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
@@ -20866,226 +20486,207 @@ static ZigType *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstructionArg
ir_add_error(ira, arg_index_inst,
buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments",
arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = fn_type_id->param_info[arg_index].type;
- if (out_val->data.x_type == nullptr) {
+ ZigType *result_type = fn_type_id->param_info[arg_index].type;
+ if (result_type == nullptr) {
// Args are only unresolved if our function is generic.
assert(fn_type->data.fn.is_generic);
ir_add_error(ira, arg_index_inst,
buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic",
arg_index, buf_ptr(&fn_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
-
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, result_type);
}
-static ZigType *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstructionTagType *instruction) {
+static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstructionTagType *instruction) {
Error err;
- IrInstruction *target_inst = instruction->target->other;
+ IrInstruction *target_inst = instruction->target->child;
ZigType *enum_type = ir_resolve_type(ira, target_inst);
if (type_is_invalid(enum_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (enum_type->id == ZigTypeIdEnum) {
if ((err = ensure_complete_type(ira->codegen, enum_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = enum_type->data.enumeration.tag_int_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);
} else if (enum_type->id == ZigTypeIdUnion) {
if ((err = ensure_complete_type(ira->codegen, enum_type)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AstNode *decl_node = enum_type->data.unionation.decl_node;
if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
assert(enum_type->data.unionation.tag_type != nullptr);
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = enum_type->data.unionation.tag_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, enum_type->data.unionation.tag_type);
} else {
ErrorMsg *msg = ir_add_error(ira, target_inst, buf_sprintf("union '%s' has no tag",
buf_ptr(&enum_type->name)));
add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
} else {
ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'",
buf_ptr(&enum_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
-static ZigType *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) {
- IrInstruction *target_inst = instruction->target->other;
+static IrInstruction *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) {
+ IrInstruction *target_inst = instruction->target->child;
if (type_is_invalid(target_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_target = ir_implicit_cast(ira, target_inst, ira->codegen->builtin_types.entry_promise);
if (type_is_invalid(casted_target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_cancel(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_target);
result->value.type = ira->codegen->builtin_types.entry_void;
result->value.special = ConstValSpecialStatic;
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_id(IrAnalyze *ira, IrInstructionCoroId *instruction) {
- IrInstruction *promise_ptr = instruction->promise_ptr->other;
+static IrInstruction *ir_analyze_instruction_coro_id(IrAnalyze *ira, IrInstructionCoroId *instruction) {
+ IrInstruction *promise_ptr = instruction->promise_ptr->child;
if (type_is_invalid(promise_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_id(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
promise_ptr);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_usize;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_alloc(IrAnalyze *ira, IrInstructionCoroAlloc *instruction) {
- IrInstruction *coro_id = instruction->coro_id->other;
+static IrInstruction *ir_analyze_instruction_coro_alloc(IrAnalyze *ira, IrInstructionCoroAlloc *instruction) {
+ IrInstruction *coro_id = instruction->coro_id->child;
if (type_is_invalid(coro_id->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_alloc(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
coro_id);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_bool;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_size(IrAnalyze *ira, IrInstructionCoroSize *instruction) {
+static IrInstruction *ir_analyze_instruction_coro_size(IrAnalyze *ira, IrInstructionCoroSize *instruction) {
IrInstruction *result = ir_build_coro_size(&ira->new_irb, instruction->base.scope, instruction->base.source_node);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_usize;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstructionCoroBegin *instruction) {
- IrInstruction *coro_id = instruction->coro_id->other;
+static IrInstruction *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstructionCoroBegin *instruction) {
+ IrInstruction *coro_id = instruction->coro_id->child;
if (type_is_invalid(coro_id->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *coro_mem_ptr = instruction->coro_mem_ptr->other;
+ IrInstruction *coro_mem_ptr = instruction->coro_mem_ptr->child;
if (type_is_invalid(coro_mem_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
assert(fn_entry != nullptr);
IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
coro_id, coro_mem_ptr);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {
- IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base, instruction->id);
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+static IrInstruction *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {
+ return ir_get_implicit_allocator(ira, &instruction->base, instruction->id);
}
-static ZigType *ir_analyze_instruction_coro_alloc_fail(IrAnalyze *ira, IrInstructionCoroAllocFail *instruction) {
- IrInstruction *err_val = instruction->err_val->other;
+static IrInstruction *ir_analyze_instruction_coro_alloc_fail(IrAnalyze *ira, IrInstructionCoroAllocFail *instruction) {
+ IrInstruction *err_val = instruction->err_val->child;
if (type_is_invalid(err_val->value.type))
return ir_unreach_error(ira);
IrInstruction *result = ir_build_coro_alloc_fail(&ira->new_irb, instruction->base.scope, instruction->base.source_node, err_val);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_unreachable;
- return ir_finish_anal(ira, result->value.type);
+ return ir_finish_anal(ira, result);
}
-static ZigType *ir_analyze_instruction_coro_suspend(IrAnalyze *ira, IrInstructionCoroSuspend *instruction) {
+static IrInstruction *ir_analyze_instruction_coro_suspend(IrAnalyze *ira, IrInstructionCoroSuspend *instruction) {
IrInstruction *save_point = nullptr;
if (instruction->save_point != nullptr) {
- save_point = instruction->save_point->other;
+ save_point = instruction->save_point->child;
if (type_is_invalid(save_point->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *is_final = instruction->is_final->other;
+ IrInstruction *is_final = instruction->is_final->child;
if (type_is_invalid(is_final->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_suspend(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, save_point, is_final);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_u8;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_end(IrAnalyze *ira, IrInstructionCoroEnd *instruction) {
+static IrInstruction *ir_analyze_instruction_coro_end(IrAnalyze *ira, IrInstructionCoroEnd *instruction) {
IrInstruction *result = ir_build_coro_end(&ira->new_irb, instruction->base.scope,
instruction->base.source_node);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_void;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_free(IrAnalyze *ira, IrInstructionCoroFree *instruction) {
- IrInstruction *coro_id = instruction->coro_id->other;
+static IrInstruction *ir_analyze_instruction_coro_free(IrAnalyze *ira, IrInstructionCoroFree *instruction) {
+ IrInstruction *coro_id = instruction->coro_id->child;
if (type_is_invalid(coro_id->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *coro_handle = instruction->coro_handle->other;
+ IrInstruction *coro_handle = instruction->coro_handle->child;
if (type_is_invalid(coro_handle->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_free(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, coro_id, coro_handle);
- ir_link_new_instruction(result, &instruction->base);
ZigType *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
result->value.type = get_optional_type(ira->codegen, ptr_type);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
- IrInstruction *awaiter_handle = instruction->awaiter_handle->other;
+static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
+ IrInstruction *awaiter_handle = instruction->awaiter_handle->child;
if (type_is_invalid(awaiter_handle->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_target = ir_implicit_cast(ira, awaiter_handle, ira->codegen->builtin_types.entry_promise);
if (type_is_invalid(casted_target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_resume(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, casted_target);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_void;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstructionCoroSave *instruction) {
- IrInstruction *coro_handle = instruction->coro_handle->other;
+static IrInstruction *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstructionCoroSave *instruction) {
+ IrInstruction *coro_handle = instruction->coro_handle->child;
if (type_is_invalid(coro_handle->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_save(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, coro_handle);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_usize;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_promise(IrAnalyze *ira, IrInstructionCoroPromise *instruction) {
- IrInstruction *coro_handle = instruction->coro_handle->other;
+static IrInstruction *ir_analyze_instruction_coro_promise(IrAnalyze *ira, IrInstructionCoroPromise *instruction) {
+ IrInstruction *coro_handle = instruction->coro_handle->child;
if (type_is_invalid(coro_handle->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (coro_handle->value.type->id != ZigTypeIdPromise ||
coro_handle->value.type->data.promise.result_type == nullptr)
{
ir_add_error(ira, &instruction->base, buf_sprintf("expected promise->T, found '%s'",
buf_ptr(&coro_handle->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
ZigType *coro_frame_type = get_promise_frame_type(ira->codegen,
@@ -21093,26 +20694,24 @@ static ZigType *ir_analyze_instruction_coro_promise(IrAnalyze *ira, IrInstructio
IrInstruction *result = ir_build_coro_promise(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, coro_handle);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = get_pointer_to_type(ira->codegen, coro_frame_type, false);
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira, IrInstructionCoroAllocHelper *instruction) {
- IrInstruction *alloc_fn = instruction->alloc_fn->other;
+static IrInstruction *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira, IrInstructionCoroAllocHelper *instruction) {
+ IrInstruction *alloc_fn = instruction->alloc_fn->child;
if (type_is_invalid(alloc_fn->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *coro_size = instruction->coro_size->other;
+ IrInstruction *coro_size = instruction->coro_size->child;
if (type_is_invalid(coro_size->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_coro_alloc_helper(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, alloc_fn, coro_size);
- ir_link_new_instruction(result, &instruction->base);
ZigType *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
result->value.type = get_optional_type(ira->codegen, u8_ptr_type);
- return result->value.type;
+ return result;
}
static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op) {
@@ -21147,48 +20746,48 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
return operand_type;
}
-static ZigType *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionAtomicRmw *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->other);
+static IrInstruction *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionAtomicRmw *instruction) {
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
if (type_is_invalid(operand_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *ptr_inst = instruction->ptr->other;
+ IrInstruction *ptr_inst = instruction->ptr->child;
if (type_is_invalid(ptr_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
// 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_inst, ptr_type);
if (type_is_invalid(casted_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AtomicRmwOp op;
if (instruction->op == nullptr) {
op = instruction->resolved_op;
} else {
- if (!ir_resolve_atomic_rmw_op(ira, instruction->op->other, &op)) {
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_atomic_rmw_op(ira, instruction->op->child, &op)) {
+ return ira->codegen->invalid_instruction;
}
}
- IrInstruction *operand = instruction->operand->other;
+ IrInstruction *operand = instruction->operand->child;
if (type_is_invalid(operand->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_operand = ir_implicit_cast(ira, operand, operand_type);
if (type_is_invalid(casted_operand->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AtomicOrder ordering;
if (instruction->ordering == nullptr) {
ordering = instruction->resolved_ordering;
} else {
- if (!ir_resolve_atomic_order(ira, instruction->ordering->other, &ordering))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
+ return ira->codegen->invalid_instruction;
if (ordering == AtomicOrderUnordered) {
ir_add_error(ira, instruction->ordering,
buf_sprintf("@atomicRmw atomic ordering must not be Unordered"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
}
@@ -21200,74 +20799,69 @@ static ZigType *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionA
IrInstruction *result = ir_build_atomic_rmw(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, casted_ptr, nullptr, casted_operand, nullptr,
op, ordering);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = operand_type;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstructionAtomicLoad *instruction) {
- ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->other);
+static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstructionAtomicLoad *instruction) {
+ ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
if (type_is_invalid(operand_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *ptr_inst = instruction->ptr->other;
+ IrInstruction *ptr_inst = instruction->ptr->child;
if (type_is_invalid(ptr_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, true);
IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
if (type_is_invalid(casted_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
AtomicOrder ordering;
if (instruction->ordering == nullptr) {
ordering = instruction->resolved_ordering;
} else {
- if (!ir_resolve_atomic_order(ira, instruction->ordering->other, &ordering))
- return ira->codegen->builtin_types.entry_invalid;
+ if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
+ return ira->codegen->invalid_instruction;
}
if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) {
assert(instruction->ordering != nullptr);
ir_add_error(ira, instruction->ordering,
buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(casted_ptr)) {
IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);
- ir_link_new_instruction(result, &instruction->base);
assert(result->value.type != nullptr);
- return result->value.type;
+ return result;
}
IrInstruction *result = ir_build_atomic_load(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, casted_ptr, nullptr, ordering);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = operand_type;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_promise_result_type(IrAnalyze *ira, IrInstructionPromiseResultType *instruction) {
- ZigType *promise_type = ir_resolve_type(ira, instruction->promise_type->other);
+static IrInstruction *ir_analyze_instruction_promise_result_type(IrAnalyze *ira, IrInstructionPromiseResultType *instruction) {
+ ZigType *promise_type = ir_resolve_type(ira, instruction->promise_type->child);
if (type_is_invalid(promise_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (promise_type->id != ZigTypeIdPromise || promise_type->data.promise.result_type == nullptr) {
ir_add_error(ira, &instruction->base, buf_sprintf("expected promise->T, found '%s'",
buf_ptr(&promise_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_type = promise_type->data.promise.result_type;
- return ira->codegen->builtin_types.entry_type;
+ return ir_const_type(ira, &instruction->base, promise_type->data.promise.result_type);
}
-static ZigType *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, IrInstructionAwaitBookkeeping *instruction) {
- ZigType *promise_result_type = ir_resolve_type(ira, instruction->promise_result_type->other);
+static IrInstruction *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, IrInstructionAwaitBookkeeping *instruction) {
+ ZigType *promise_result_type = ir_resolve_type(ira, instruction->promise_result_type->child);
if (type_is_invalid(promise_result_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
assert(fn_entry != nullptr);
@@ -21276,17 +20870,15 @@ static ZigType *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, IrInstr
fn_entry->calls_or_awaits_errorable_fn = true;
}
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->type = ira->codegen->builtin_types.entry_void;
- return out_val->type;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira,
+static IrInstruction *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira,
IrInstructionMergeErrRetTraces *instruction)
{
- IrInstruction *coro_promise_ptr = instruction->coro_promise_ptr->other;
+ IrInstruction *coro_promise_ptr = instruction->coro_promise_ptr->child;
if (type_is_invalid(coro_promise_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
assert(coro_promise_ptr->value.type->id == ZigTypeIdPointer);
ZigType *promise_frame_type = coro_promise_ptr->value.type->data.pointer.child_type;
@@ -21294,71 +20886,67 @@ static ZigType *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira,
ZigType *promise_result_type = promise_frame_type->data.structure.fields[1].type_entry;
if (!type_can_fail(promise_result_type)) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->type = ira->codegen->builtin_types.entry_void;
- return out_val->type;
+ return ir_const_void(ira, &instruction->base);
}
- IrInstruction *src_err_ret_trace_ptr = instruction->src_err_ret_trace_ptr->other;
+ IrInstruction *src_err_ret_trace_ptr = instruction->src_err_ret_trace_ptr->child;
if (type_is_invalid(src_err_ret_trace_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *dest_err_ret_trace_ptr = instruction->dest_err_ret_trace_ptr->other;
+ IrInstruction *dest_err_ret_trace_ptr = instruction->dest_err_ret_trace_ptr->child;
if (type_is_invalid(dest_err_ret_trace_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_merge_err_ret_traces(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_void;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) {
+static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) {
IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope,
instruction->base.source_node);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_void;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_mark_err_ret_trace_ptr(IrAnalyze *ira, IrInstructionMarkErrRetTracePtr *instruction) {
- IrInstruction *err_ret_trace_ptr = instruction->err_ret_trace_ptr->other;
+static IrInstruction *ir_analyze_instruction_mark_err_ret_trace_ptr(IrAnalyze *ira, IrInstructionMarkErrRetTracePtr *instruction) {
+ IrInstruction *err_ret_trace_ptr = instruction->err_ret_trace_ptr->child;
if (type_is_invalid(err_ret_trace_ptr->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *result = ir_build_mark_err_ret_trace_ptr(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, err_ret_trace_ptr);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = ira->codegen->builtin_types.entry_void;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionSqrt *instruction) {
- ZigType *float_type = ir_resolve_type(ira, instruction->type->other);
+static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionSqrt *instruction) {
+ ZigType *float_type = ir_resolve_type(ira, instruction->type->child);
if (type_is_invalid(float_type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *op = instruction->op->other;
+ IrInstruction *op = instruction->op->child;
if (type_is_invalid(op->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
bool ok_type = float_type->id == ZigTypeIdComptimeFloat || float_type->id == ZigTypeIdFloat;
if (!ok_type) {
ir_add_error(ira, instruction->type, buf_sprintf("@sqrt does not support type '%s'", buf_ptr(&float_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstruction *casted_op = ir_implicit_cast(ira, op, float_type);
if (type_is_invalid(casted_op->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(casted_op)) {
ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
if (!val)
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ IrInstruction *result = ir_const(ira, &instruction->base, float_type);
+ ConstExprValue *out_val = &result->value;
if (float_type->id == ZigTypeIdComptimeFloat) {
bigfloat_sqrt(&out_val->data.x_bigfloat, &val->data.x_bigfloat);
@@ -21383,7 +20971,7 @@ static ZigType *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionSqrt *i
zig_unreachable();
}
- return float_type;
+ return result;
}
assert(float_type->id == ZigTypeIdFloat);
@@ -21391,93 +20979,87 @@ static ZigType *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionSqrt *i
float_type->data.floating.bit_count != 32 &&
float_type->data.floating.bit_count != 64) {
ir_add_error(ira, instruction->type, buf_sprintf("compiler TODO: add implementation of sqrt for '%s'", buf_ptr(&float_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
IrInstruction *result = ir_build_sqrt(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, casted_op);
- ir_link_new_instruction(result, &instruction->base);
result->value.type = float_type;
- return result->value.type;
+ return result;
}
-static ZigType *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
+static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
Error err;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (target->value.type->id != ZigTypeIdEnum) {
ir_add_error(ira, instruction->target,
buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;
- IrInstruction *result = ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);
}
-static ZigType *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
+static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
Error err;
- IrInstruction *dest_type_value = instruction->dest_type->other;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_type->id != ZigTypeIdEnum) {
ir_add_error(ira, instruction->dest_type,
buf_sprintf("expected enum, found type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
ZigType *tag_type = dest_type->data.enumeration.tag_int_type;
- IrInstruction *target = instruction->target->other;
+ IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
IrInstruction *casted_target = ir_implicit_cast(ira, target, tag_type);
if (type_is_invalid(casted_target->value.type))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_analyze_int_to_enum(ira, &instruction->base, casted_target, dest_type);
- ir_link_new_instruction(result, &instruction->base);
- return result->value.type;
+ return ir_analyze_int_to_enum(ira, &instruction->base, casted_target, dest_type);
}
-static ZigType *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira, IrInstructionCheckRuntimeScope *instruction) {
- IrInstruction *block_comptime_inst = instruction->scope_is_comptime->other;
+static IrInstruction *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira, IrInstructionCheckRuntimeScope *instruction) {
+ IrInstruction *block_comptime_inst = instruction->scope_is_comptime->child;
bool scope_is_comptime;
if (!ir_resolve_bool(ira, block_comptime_inst, &scope_is_comptime))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- IrInstruction *is_comptime_inst = instruction->is_comptime->other;
+ IrInstruction *is_comptime_inst = instruction->is_comptime->child;
bool is_comptime;
if (!ir_resolve_bool(ira, is_comptime_inst, &is_comptime))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (!scope_is_comptime && is_comptime) {
ErrorMsg *msg = ir_add_error(ira, &instruction->base,
buf_sprintf("comptime control flow inside runtime block"));
add_error_note(ira->codegen, msg, block_comptime_inst->source_node,
buf_sprintf("runtime block created here"));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- ir_build_const_from(ira, &instruction->base);
- return ira->codegen->builtin_types.entry_void;
+ return ir_const_void(ira, &instruction->base);
}
-static ZigType *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
+static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdWidenOrShorten:
@@ -21761,19 +21343,11 @@ static ZigType *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *ins
zig_unreachable();
}
-static ZigType *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {
- ZigType *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
- instruction->value.type = instruction_type;
-
- if (instruction->other) {
- instruction->other->value.type = instruction_type;
- } else {
- assert(instruction_type->id == ZigTypeIdInvalid ||
- instruction_type->id == ZigTypeIdUnreachable);
- instruction->other = instruction;
- }
-
- return instruction_type;
+static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {
+ IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);
+ assert(new_instruction->value.type != nullptr);
+ old_instruction->child = new_instruction;
+ return new_instruction;
}
// This function attempts to evaluate IR code while doing type checking and other analysis.
@@ -21820,13 +21394,13 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
continue;
}
- ZigType *return_type = ir_analyze_instruction(ira, old_instruction);
- if (type_is_invalid(return_type) && ir_should_inline(new_exec, old_instruction->scope)) {
+ 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;
}
// unreachable instructions do their own control flow.
- if (return_type->id == ZigTypeIdUnreachable)
+ if (new_instruction->value.type->id == ZigTypeIdUnreachable)
continue;
ira->instruction_index += 1;
From d07413f9b77a1e8e27ba09d2183ba5d614268c76 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 4 Oct 2018 18:14:57 -0400
Subject: [PATCH 072/127] fix missing .h files
closes #1634
---
CMakeLists.txt | 11 +++++++++++
src/ir.cpp | 8 ++++++++
2 files changed, 19 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c1ea43943d..cff70950de 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -649,7 +649,9 @@ set(ZIG_C_HEADER_FILES
"__clang_cuda_builtin_vars.h"
"__clang_cuda_cmath.h"
"__clang_cuda_complex_builtins.h"
+ "__clang_cuda_device_functions.h"
"__clang_cuda_intrinsics.h"
+ "__clang_cuda_libdevice_declares.h"
"__clang_cuda_math_forward_declares.h"
"__clang_cuda_runtime_wrapper.h"
"__stddef_max_align_t.h"
@@ -660,6 +662,7 @@ set(ZIG_C_HEADER_FILES
"ammintrin.h"
"arm64intr.h"
"arm_acle.h"
+ "arm_fp16.h"
"arm_neon.h"
"armintr.h"
"avx2intrin.h"
@@ -689,6 +692,7 @@ set(ZIG_C_HEADER_FILES
"bmi2intrin.h"
"bmiintrin.h"
"cetintrin.h"
+ "cldemoteintrin.h"
"clflushoptintrin.h"
"clwbintrin.h"
"clzerointrin.h"
@@ -709,6 +713,7 @@ set(ZIG_C_HEADER_FILES
"immintrin.h"
"intrin.h"
"inttypes.h"
+ "invpcidintrin.h"
"iso646.h"
"limits.h"
"lwpintrin.h"
@@ -717,17 +722,21 @@ set(ZIG_C_HEADER_FILES
"mm_malloc.h"
"mmintrin.h"
"module.modulemap"
+ "movdirintrin.h"
"msa.h"
"mwaitxintrin.h"
"nmmintrin.h"
"opencl-c.h"
+ "pconfigintrin.h"
"pkuintrin.h"
"pmmintrin.h"
"popcntintrin.h"
"prfchwintrin.h"
+ "ptwriteintrin.h"
"rdseedintrin.h"
"rtmintrin.h"
"s390intrin.h"
+ "sgxintrin.h"
"shaintrin.h"
"smmintrin.h"
"stdalign.h"
@@ -746,6 +755,8 @@ set(ZIG_C_HEADER_FILES
"varargs.h"
"vecintrin.h"
"vpclmulqdqintrin.h"
+ "waitpkgintrin.h"
+ "wbnoinvdintrin.h"
"wmmintrin.h"
"x86intrin.h"
"xmmintrin.h"
diff --git a/src/ir.cpp b/src/ir.cpp
index 09d6fca7e7..c48b56255d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17153,6 +17153,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
}
static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
+ Error err;
ZigType *attrs_type;
uint32_t size_enum_index;
if (is_slice(ptr_type_entry)) {
@@ -17165,6 +17166,9 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
zig_unreachable();
}
+ if ((err = type_resolve(ira->codegen, attrs_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
+ return nullptr;
+
ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
assertNoError(ensure_complete_type(ira->codegen, type_info_pointer_type));
@@ -17308,6 +17312,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
case ZigTypeIdPointer:
{
result = create_ptr_like_type_info(ira, type_entry);
+ if (result == nullptr)
+ return ErrorSemanticAnalyzeFail;
break;
}
case ZigTypeIdArray:
@@ -17586,6 +17592,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
{
if (type_entry->data.structure.is_slice) {
result = create_ptr_like_type_info(ira, type_entry);
+ if (result == nullptr)
+ return ErrorSemanticAnalyzeFail;
break;
}
From 8d6601d7ce6adb22103892f50176e4e2a60fe2fc Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 4 Oct 2018 22:51:36 -0400
Subject: [PATCH 073/127] improve pointer documentation
closes #1630
---
doc/langref.html.in | 197 +++++++++++++++++++++++++++++---------------
1 file changed, 132 insertions(+), 65 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 3485fda815..ad69e67578 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1504,7 +1504,46 @@ test "array initialization with function calls" {
{#see_also|for|Slices#}
{#header_close#}
{#header_open|Pointers#}
- {#code_begin|test#}
+
+ Zig has two kinds of pointers:
+
+
+ - {#syntax#}*T{#endsyntax#} - pointer to exactly one item.
+
+ - Supports deref syntax: {#syntax#}ptr.*{#endsyntax#}
+
+
+ - {#syntax#}[*]T{#endsyntax#} - pointer to unknown number of items.
+
+ - Supports index syntax: {#syntax#}ptr[i]{#endsyntax#}
+ - Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}
+ - Supports pointer arithmetic: {#syntax#}ptr + x{#endsyntax#}, {#syntax#}ptr - x{#endsyntax#}
+ - {#syntax#}T{#endsyntax#} must have a known size, which means that it cannot be
+ {#syntax#}c_void{#endsyntax#} or any other {#link|@OpaqueType#}.
+
+
+
+ These types are closely related to {#link|Arrays#} and {#link|Slices#}:
+
+ - {#syntax#}*[N]T{#endsyntax#} - pointer to N items, same as single-item pointer to array.
+
+ - Supports index syntax: {#syntax#}array_ptr[i]{#endsyntax#}
+ - Supports slice syntax: {#syntax#}array_ptr[start..end]{#endsyntax#}
+ - Supports len property: {#syntax#}array_ptr.len{#endsyntax#}
+
+
+
+
+ - {#syntax#}[]T{#endsyntax#} - pointer to runtime-known number of items.
+
+ - Supports index syntax: {#syntax#}slice[i]{#endsyntax#}
+ - Supports slice syntax: {#syntax#}slice[start..end]{#endsyntax#}
+ - Supports len property: {#syntax#}slice.len{#endsyntax#}
+
+
+
+ Use {#syntax#}&x{#endsyntax#} to obtain a single-item pointer:
+ {#code_begin|test#}
const assert = @import("std").debug.assert;
test "address of syntax" {
@@ -1515,7 +1554,7 @@ test "address of syntax" {
// Deference a pointer:
assert(x_ptr.* == 1234);
- // When you get the address of a const variable, you get a const pointer.
+ // When you get the address of a const variable, you get a const pointer to a single item.
assert(@typeOf(x_ptr) == *const i32);
// If you want to mutate the value, you'd need an address of a mutable variable:
@@ -1538,82 +1577,101 @@ test "pointer array access" {
ptr.* += 1;
assert(array[2] == 4);
}
+ {#code_end#}
+
+ In Zig, we prefer slices over pointers to null-terminated arrays.
+ You can turn an array or pointer into a slice using slice syntax.
+
+
+ Slices have bounds checking and are therefore protected
+ against this kind of undefined behavior. This is one reason
+ we prefer slices to pointers.
+
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
test "pointer slicing" {
- // In Zig, we prefer slices over pointers to null-terminated arrays.
- // You can turn an array into a slice using slice syntax:
var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
const slice = array[2..4];
assert(slice.len == 2);
- // Slices have bounds checking and are therefore protected
- // against this kind of undefined behavior. This is one reason
- // we prefer slices to pointers.
assert(array[3] == 4);
slice[1] += 1;
assert(array[3] == 5);
}
+ {#code_end#}
+ Pointers work at compile-time too, as long as the code does not depend on
+ an undefined memory layout:
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
-comptime {
- // Pointers work at compile-time too, as long as you don't use
- // @ptrCast.
- var x: i32 = 1;
- const ptr = &x;
- ptr.* += 1;
- x += 1;
- assert(ptr.* == 3);
+test "comptime pointers" {
+ comptime {
+ var x: i32 = 1;
+ const ptr = &x;
+ ptr.* += 1;
+ x += 1;
+ assert(ptr.* == 3);
+ }
}
+ {#code_end#}
+ To convert an integer address into a pointer, use {#syntax#}@intToPtr{#endsyntax#}.
+ To convert a pointer to an integer, use {#syntax#}@ptrToInt{#endsyntax#}:
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
test "@ptrToInt and @intToPtr" {
- // To convert an integer address into a pointer, use @intToPtr:
- const ptr = @intToPtr(*i32, 0xdeadbeef);
-
- // To convert a pointer to an integer, use @ptrToInt:
- const addr = @ptrToInt(ptr);
-
- assert(@typeOf(addr) == usize);
- assert(addr == 0xdeadbeef);
-}
-
-comptime {
- // Zig is able to do this at compile-time, as long as
- // ptr is never dereferenced.
const ptr = @intToPtr(*i32, 0xdeadbeef);
const addr = @ptrToInt(ptr);
assert(@typeOf(addr) == usize);
assert(addr == 0xdeadbeef);
}
+ {#code_end#}
+ Zig is able to preserve memory addresses in comptime code, as long as
+ the pointer is never dereferenced:
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
+
+test "comptime @intToPtr" {
+ comptime {
+ // Zig is able to do this at compile-time, as long as
+ // ptr is never dereferenced.
+ const ptr = @intToPtr(*i32, 0xdeadbeef);
+ const addr = @ptrToInt(ptr);
+ assert(@typeOf(addr) == usize);
+ assert(addr == 0xdeadbeef);
+ }
+}
+ {#code_end#}
+ {#see_also|Optional Pointers#}
+ {#header_open|volatile#}
+ Loads and stores are assumed to not have side effects. If a given load or store
+ should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
+ In the following code, loads and stores with {#syntax#}mmio_ptr{#endsyntax#} are guaranteed to all happen
+ and in the same order as in source code:
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
test "volatile" {
- // In Zig, loads and stores are assumed to not have side effects.
- // If a given load or store should have side effects, such as
- // Memory Mapped Input/Output (MMIO), use `volatile`:
const mmio_ptr = @intToPtr(*volatile u8, 0x12345678);
-
- // Now loads and stores with mmio_ptr are guaranteed to all happen
- // and in the same order as in source code.
assert(@typeOf(mmio_ptr) == *volatile u8);
}
-
-test "optional pointers" {
- // Pointers cannot be null. If you want a null pointer, use the optional
- // prefix `?` to make the pointer type optional.
- var ptr: ?*i32 = null;
-
- var x: i32 = 1;
- ptr = &x;
-
- assert(ptr.?.* == 1);
-
- // Optional pointers are the same size as normal pointers, because pointer
- // value 0 is used as the null value.
- assert(@sizeOf(?*i32) == @sizeOf(*i32));
-}
+ {#code_end#}
+
+ Note that {#syntax#}volatile{#endsyntax#} is unrelated to concurrency and {#link|Atomics#}.
+ If you see code that is using {#syntax#}volatile{#endsyntax#} for something other than Memory Mapped
+ Input/Output, it is probably a bug.
+
+ {#header_close#}
+
+ To convert one pointer type to another, use {#link|@ptrCast#}. This is an unsafe
+ operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other
+ conversions are not possible.
+
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
test "pointer casting" {
- // To convert one pointer type to another, use @ptrCast. This is an unsafe
- // operation that Zig cannot protect you against. Use @ptrCast only when other
- // conversions are not possible.
const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
const u32_ptr = @ptrCast(*const u32, &bytes);
assert(u32_ptr.* == 0x12121212);
@@ -1714,19 +1772,6 @@ fn foo(bytes: []u8) u32 {
}
{#code_end#}
{#header_close#}
- {#header_open|Type Based Alias Analysis#}
- Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
- perform some optimizations. This means that pointers of different types must
- not alias the same memory, with the exception of {#syntax#}u8{#endsyntax#}. Pointers to
- {#syntax#}u8{#endsyntax#} can alias any memory.
-
- As an example, this code produces undefined behavior:
- {#syntax#}@ptrCast(*u32, f32(12.34)).*{#endsyntax#}
- Instead, use {#link|@bitCast#}:
-
{#syntax#}@bitCast(u32, f32(12.34)){#endsyntax#}
- As an added benefit, the {#syntax#}@bitCast{#endsyntax#} version works at compile-time.
- {#see_also|Slices|Memory#}
- {#header_close#}
{#header_close#}
{#header_open|Slices#}
{#code_begin|test_safety|index out of bounds#}
@@ -3816,6 +3861,28 @@ test "optional type" {
{#code_begin|syntax#}
const optional_value: ?i32 = null;
+ {#code_end#}
+ {#header_close#}
+ {#header_open|Optional Pointers#}
+ An optional pointer is guaranteed to be the same size as a pointer. The {#syntax#}null{#endsyntax#} of
+ the optional is guaranteed to be address 0.
+ {#code_begin|test#}
+const assert = @import("std").debug.assert;
+
+test "optional pointers" {
+ // Pointers cannot be null. If you want a null pointer, use the optional
+ // prefix `?` to make the pointer type optional.
+ var ptr: ?*i32 = null;
+
+ var x: i32 = 1;
+ ptr = &x;
+
+ assert(ptr.?.* == 1);
+
+ // Optional pointers are the same size as normal pointers, because pointer
+ // value 0 is used as the null value.
+ assert(@sizeOf(?*i32) == @sizeOf(*i32));
+}
{#code_end#}
{#header_close#}
{#header_close#}
From c81a4b3e3d75577b69f37f57a21d2434019fa41d Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 5 Oct 2018 10:21:08 -0400
Subject: [PATCH 074/127] docs: fix double escaping html entities
---
doc/langref.html.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index ad69e67578..891e14d8f1 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1024,7 +1024,7 @@ a &= b{#endsyntax#}
- {#syntax#}0b011 & 0b101 == 0b001{#endsyntax#}
+ {#syntax#}0b011 & 0b101 == 0b001{#endsyntax#}
|
@@ -1345,7 +1345,7 @@ x.* == 1234{#endsyntax#}
- {#syntax#}&a{#endsyntax#} |
+ {#syntax#}&a{#endsyntax#} |
All types
|
@@ -5888,7 +5888,7 @@ mem.set(u8, dest, c);{#endsyntax#}
{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}
Modulus division. For unsigned integers this is the same as
- {#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}.
+ {#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}.