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 ef37d657dcfe43d3f60bfc6492e0cd3758e06910..f28c8d6cfad2110f21935c7839e7f3e383708a3c 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 7daff2ca0efcd01b7f17b66c2f66bf385b09ad63..5e0f79ec13f71db8b8fef49c7a38218f737882b8 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 2e238e40eb1221396f76b50ddfaa3887a4ee0d0d..86c5e4828e5ad5d37c8574e06444899eb37ec39a 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 2d1ffa943477075c67de75ac8bc9513580a0e607..11c6b2f6ba36c9c355b50dae4c724bc9d14ede34 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 7b659a8dc11de0df0a14872027664ac6e0ac5f5a..fae022f3fbf2a586e682a409690e38816f2b1f54 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(
--
2.54.0
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 5e0f79ec13f71db8b8fef49c7a38218f737882b8..c9bc4a48ef4d850fc43bb0a5302dc4790ea4a133 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 6e64a64aeecf471449522bec06665573028464a6..e0c998e9619dbc561e842faa0a165d44aa861cce 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"));
+}
--
2.54.0
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 | 101 ++++++++++++++++++---------------------
test/behavior.zig | 1 +
test/cases/bugs/1486.zig | 11 +++++
test/compile_errors.zig | 2 +-
4 files changed, 59 insertions(+), 56 deletions(-)
create mode 100644 test/cases/bugs/1486.zig
diff --git a/src/ir.cpp b/src/ir.cpp
index c9bc4a48ef4d850fc43bb0a5302dc4790ea4a133..a35c6380a7e55a07498ffb3b9bb3201525e0fef4 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,34 +11207,42 @@ 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;
+ // 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,
+ source_instruction->source_node, child_type);
+ 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 = ir_const_ptr_pointee(ira, &ptr->value, source_instruction->source_node);
- if (pointee == nullptr)
- return ira->codegen->invalid_instruction;
+ 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);
- copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst);
+
+ 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;
}
}
}
- // 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,
- source_instruction->source_node, child_type);
- init_const_unsigned_negative(&result->value, child_type, 0, false);
- 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 68d6f513c45fe6a030096af7f22f53aa189e7a77..1d031343d68494990d845e6fe65a014622dde232 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 0000000000000000000000000000000000000000..98fae36d3a0f58223f4c4a62d310fab044a05f2e
--- /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 fae022f3fbf2a586e682a409690e38816f2b1f54..c1e25c1df9a96a52a2d7368cc74cdfc88859d5b8 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(
--
2.54.0
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 a35c6380a7e55a07498ffb3b9bb3201525e0fef4..7e98e99af10629aa134fb3657e0b60130f1e121e 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 c1e25c1df9a96a52a2d7368cc74cdfc88859d5b8..62df9f077d42da91425c3329ca744af3b1dba3ab 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 {
--
2.54.0
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 f28c8d6cfad2110f21935c7839e7f3e383708a3c..40af140c83db34eb51accd0249647197ea84d18b 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#}
--
2.54.0
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 7e98e99af10629aa134fb3657e0b60130f1e121e..95172e2b590c7f3ab6efd9242ad720b7852bb8f1 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 62df9f077d42da91425c3329ca744af3b1dba3ab..5d9fb84c71ff4bdad82add4a8b47705ecaa64e39 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(
--
2.54.0
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 b6824298848484770cc56664db6854713358fade..54df5568b7aba16dea807d27999ec279078db20c 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;
--
2.54.0
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 8639a0c56a9471a9047ea94b0674f4e45339b55b..cdad0509e6489a32a1586eb4b6188f365ecd83bc 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"
--
2.54.0
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 d4110bd759d66516e41af916a4daa130c6fd23d4..d86ab119dfdcfb1e32568df761461cb5b66c8ad7 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();
--
2.54.0
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 f65dabc9f55c86e323e6fd16e45551e2430058d0..0ca806a3035cc8c6646b79265129fa145644b1ed 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);
+}
--
2.54.0
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 0ca806a3035cc8c6646b79265129fa145644b1ed..45e961053b588d793ceafb46056db9c2d9859b28 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{
--
2.54.0
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 45e961053b588d793ceafb46056db9c2d9859b28..5a2a51bbfd0d79f56137db51c45f2efcd77513d9 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");
--
2.54.0
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 df48c9e4a2aff210a40689cf91a0486f766ebcdc..fd13adb8f6d06acbf2ff83a9f368c488b1c2a4cf 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 b31e515aa22810a9f143416fed103cefe810438f..f6ce742fcd49dcdef8279f348832644573f4fd80 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++);
--
2.54.0
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 fd13adb8f6d06acbf2ff83a9f368c488b1c2a4cf..37d5b722c3fca1260965d46ac4e4254e87d393b0 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 ad8edb4cdac1c8ffa7660d6dcda199c090096a57..8e9fe65d472f7a991136718908a188576f32cd8e 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
--
2.54.0
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 40af140c83db34eb51accd0249647197ea84d18b..4e49db72be9275953edc7601f16fdfe263eaf976 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#}
--
2.54.0
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 bf18b9a1bfde5123468773b68a18e9d81c194029..2737057f972b03dcde984e39c6218c49cf26d950 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 e0c998e9619dbc561e842faa0a165d44aa861cce..08c02f184399a0fcba8bb9c4fd7329a0282e311a 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);
+ }
+}
--
2.54.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 f6ce742fcd49dcdef8279f348832644573f4fd80..9d8c7d9f6360c740cfaf57d6b6f86606199d8ef4 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) {
--
2.54.0
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 2737057f972b03dcde984e39c6218c49cf26d950..8a8d028e82396ed148b4825940201dd47cd666ec 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 08c02f184399a0fcba8bb9c4fd7329a0282e311a..2cd7f695e7de55e9f7534466c08004556e6517bd 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);
}
}
--
2.54.0
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 b5b3ce9add4e2daf1751d0aef8cc11084725740a..2102da456c7a1b5613b6c61c366bd882351bbc64 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 136525e0ad4590211109f215da266fad615221dd..5941ab6905bc7f806e13114198e4f2a2d275d90a 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 1bb3de49351d11b661e2e1bb31904d1676b6d3ac..b9968762005b9b8d9c22bb7771aea2571639febd 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();
--
2.54.0
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 b47f9e9b9c1e8ca9d0460b25025214e3c1acfa0a..ca80958887454772152868a0cdfea398ec0b25fd 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 4343cb3b90a2e1fbbd3b0f6cf1ee8a69e517e55a..572cee5419adc1b6f4ba74a2368fbe5cbf4dedae 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);
+}
--
2.54.0
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 b5cf2ca87b30f0d196d45280c67e508f9238b4c7..cbfd67c740d2d85a7cc6dd5a85a62ca08fe2eb3b 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 4e49db72be9275953edc7601f16fdfe263eaf976..dc307255c72adcf6cb34f51bc46d4c1ad006bd11 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");
--
2.54.0
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 ca80958887454772152868a0cdfea398ec0b25fd..650f5b6b11dc4b5481de4f781a0067b29545d11a 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 95172e2b590c7f3ab6efd9242ad720b7852bb8f1..33d42cfc5f9f733c8cf9920fcd4a6424a6212b73 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 5d9fb84c71ff4bdad82add4a8b47705ecaa64e39..d5d0cb38f203815a18d69d887fb0a6990ab2de2a 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 {
--
2.54.0
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 95fba8d59eefd460d973af2258592ddda55c0783..cdb68ec5297340c17b797556dc5629b44c1bde24 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);
}
}
--
2.54.0
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 | 114 +++++++++++++++++++++++++---------------
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, 155 insertions(+), 47 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index dc307255c72adcf6cb34f51bc46d4c1ad006bd11..bc7bbf0cbb4cdd8bff985879e565b90af4ab7849 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 33d42cfc5f9f733c8cf9920fcd4a6424a6212b73..022909d184616ec1920810e31ea8ca47ef77c1c2 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,79 +20252,75 @@ 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;
- IrInstruction *dest_type_value = instruction->dest_type->other;
- ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
- if (type_is_invalid(dest_type))
- return ira->codegen->builtin_types.entry_invalid;
-
- IrInstruction *ptr = instruction->ptr->other;
ZigType *src_type = ptr->value.type;
- if (type_is_invalid(src_type))
- return ira->codegen->builtin_types.entry_invalid;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
if (get_src_ptr_type(dest_type) == nullptr) {
- ir_add_error(ira, dest_type_value,
+ ir_add_error(ira, dest_type_src,
buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
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;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
- 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;
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
uint32_t dest_align_bytes;
if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
- return ira->codegen->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
if (dest_align_bytes > src_align_bytes) {
- ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));
+ 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_value->source_node,
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
- IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, ptr);
+ 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, &instruction->base,
+ 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_value->source_node,
+ 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->builtin_types.entry_invalid;
+ return ira->codegen->invalid_instruction;
}
// Keep the bigger alignment, it can only help-
@@ -20315,10 +20329,28 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
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;
+ 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))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *ptr = instruction->ptr->other;
+ ZigType *src_type = ptr->value.type;
+ if (type_is_invalid(src_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ 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;
}
diff --git a/std/event/tcp.zig b/std/event/tcp.zig
index 5715e46a6228c9b051d40ccf311892d2952f6fa8..c1e6e891cde05194442ef34d7ae05d524664ac6f 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 d86ab119dfdcfb1e32568df761461cb5b66c8ad7..1ce9bd7278547da0649ec175f96ae16933657de2 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 c369921e14ca00aa744eb4513958efe52a82ec95..6323c89ddabbb60455c20303dc1e74e65f443a81 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 880ebfb386d719d5f6d73e4982d189191b51fd99..92148728a6f19d2ddd33196f6ad532547b68c5f6 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 d5d0cb38f203815a18d69d887fb0a6990ab2de2a..19bb630fb760f059907c59eec25a0c417cfaa78b 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 {
--
2.54.0
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 84d1d905180838d3659fabe0abdec4b3f897af18..ebe1b07359c5f82211763c0b11d65a561e276724 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: \
--
2.54.0
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 0eaf69ed64568a0d7f3cd49f3e3c484c0295ac6d..89c117ce82751bb87a47924999c2bfd05382ac48 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 650f5b6b11dc4b5481de4f781a0067b29545d11a..e0aa6224e8c069e3de3a643357792fa23e92dc70 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 b04cf6fdfdc1a57c244cc19497ca406db32c7bf6..fdc979ec9aa39bf07741b32e93bbd822d821183a 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 37d4221eef2a5e91b8044840b428fb2ccf48287e..82c245d03ac734b4f7adb41047bc238493610acf 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 d4d57d541c05ca2b713220212f9fd8bd4b81f970..176b7bb08b2230dc25da653c13de896baa8158c2 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 022909d184616ec1920810e31ea8ca47ef77c1c2..79b809349c215ea10dc25a808cd829b78efa6227 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 dc756cf492ee4db7531589c746f2e9201b087335..3bed716756b05a9469b442b158d44ecaf1556ebb 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 8e6076c5e598b191e455bb577646bddbcf063cfe..c57b1303e7b3af47a2f633c74b5c6964db6d9917 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 838935f53cef37fe4a16f9b135d411d820880135..3dff57feb882141a8f9e7cabc1f710542310beb1 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 2cd7f695e7de55e9f7534466c08004556e6517bd..408e9b04afcb5ab6d0ed3fec7126fe0fedb92eb7 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 19bb630fb760f059907c59eec25a0c417cfaa78b..96d35e4de9e38847b46fc311b5949936f583cfcb 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(
--
2.54.0
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 e0aa6224e8c069e3de3a643357792fa23e92dc70..bd1395c9c203b3d26c49517203a28b0ed1ea90a8 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 4ca013544432c7feed36552a8246c82d41913c9f..2e1b4dfbef1e9686182d6a010eb100b699fd9fb5 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);
+}
--
2.54.0
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 bd1395c9c203b3d26c49517203a28b0ed1ea90a8..ae0d67b2ec569b3cc1f458d568e48933774657a5 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 79b809349c215ea10dc25a808cd829b78efa6227..abdb3a24a3f0329f9a30e9d53f9a2176be4b7976 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 96d35e4de9e38847b46fc311b5949936f583cfcb..fb7b536be923113b1210bf4c556b723b4954bb8a 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 {
--
2.54.0
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 | 337 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 269 insertions(+), 68 deletions(-)
diff --git a/std/rand/index.zig b/std/rand/index.zig
index 2cbff049ea90286bc3897eb5a0a96fb3a01a1796..6cad865d1eefef73faf6a20efc067704eeb86502 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);
}
+ 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..]);
+
+ // 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 {
- var rand_bytes: [@sizeOf(T)]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);
- }
+ 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;
--
2.54.0
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 176b7bb08b2230dc25da653c13de896baa8158c2..70310641c4bbfd822ada030bafd7f5bf6eacc7a5 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));
--
2.54.0
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 bc7bbf0cbb4cdd8bff985879e565b90af4ab7849..3485fda8150b78154122328fff4a17d0c7aaacd6 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 {
--
2.54.0
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 64288a5ce91a3e863742edcd492471286db5684d..e6d02a4fb55b89552ac6aa329d1c4f909dae0f26 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()
--
2.54.0
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 e6d02a4fb55b89552ac6aa329d1c4f909dae0f26..70ca29b2e9a876fef60eea66d815dadb97f4a897 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()
--
2.54.0
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 70ca29b2e9a876fef60eea66d815dadb97f4a897..22f365aafe50254532a802bd8c66f45d845f329a 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}")
--
2.54.0
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 cdb68ec5297340c17b797556dc5629b44c1bde24..5c1e107362eec48f10489da3f206a9edbae112a3 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;
--
2.54.0
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 9ad15ccd7e505d72e26cde7a5ee30d04404df509..4a8ee365bafd10a3ac430f6d27294dcb7eac6c40 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,
--
2.54.0
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 ed190f7deb7d091f66694b77911aa2bf460c6e90..10068e83a8b34bac2092b6fa20c3bfbe79660bc0 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 fc64db7c3772e818a1439748f8e096a9dd10ca0f..9d03cf662522f8ca991dff38e8b797225fd02d48 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 94b339fa6ef0af141752b6a6187191ccc1963b8d..9fbd22b66a651d25933f2375b462464b4f14f8ca 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;
--
2.54.0
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 22f365aafe50254532a802bd8c66f45d845f329a..bba4dd688108b6dee70f488b4cdc928a451671ab 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}
--
2.54.0
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 10068e83a8b34bac2092b6fa20c3bfbe79660bc0..c0922003ce8d68ca59b5d98d3465a0c59b598a8d 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 1ce9bd7278547da0649ec175f96ae16933657de2..a53d1d205007010e5e75c08ecc0c918da4cde503 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 9fbd22b66a651d25933f2375b462464b4f14f8ca..7eec5faba997aa85810ac3c70ff3dda57a5fcbf3 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 6534d16f5e5abe2a56c10565170c5040af3863f7..7d983421e0d929a1d9e5a12d9f9064ac46cbcaa8 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,
--
2.54.0
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 22f365aafe50254532a802bd8c66f45d845f329a..bba4dd688108b6dee70f488b4cdc928a451671ab 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 8e9fe65d472f7a991136718908a188576f32cd8e..ea270bcb5a93d43938ebdd60201c79a8c99d63c4 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();
--
2.54.0
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 bba4dd688108b6dee70f488b4cdc928a451671ab..e99f2ea343a07c1eba1c0c9337f1ead62c39c6ac 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 bd3262a5756002a7a90911548dcdcf5b73ebf154..56c5223ba3e5f03be549efb3c8400e2e55cb063a 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
--
2.54.0
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 e99f2ea343a07c1eba1c0c9337f1ead62c39c6ac..98b2ab9db0dd3badf061988bb80fe8c5f4aecad0 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 d3a64abba37496487b84084976c6951baa6b0ff4..69c52e200c2bc9628fc2dc91e9d7228b58863712 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
--
2.54.0
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 89c117ce82751bb87a47924999c2bfd05382ac48..30d941354acac4876443b7eb90dcff6bbe16cbda 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 70310641c4bbfd822ada030bafd7f5bf6eacc7a5..de69b53388c47e46b95c338af6923466e8411344 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 aa0edde61b7a9c5ff7b148990a04e6279453d911..a280c31f74d26fcc7fe6d6f9b3799a266e534a75 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 5c1e107362eec48f10489da3f206a9edbae112a3..f9df802cb36c25df1f1965442dac92d52d33f3b8 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));
--
2.54.0
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 | 260 +++++++++++++++++------
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, 437 insertions(+), 257 deletions(-)
create mode 100644 std/event/io.zig
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 98b2ab9db0dd3badf061988bb80fe8c5f4aecad0..25c0dfa12628c1757808a68ba23e0bc6a3594350 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 cbfd67c740d2d85a7cc6dd5a85a62ca08fe2eb3b..2e2aa4b4204ee43aa65dffaabd7ef1df5676d74b 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 062f93e7f7fa08a37b6935be9816454c0a8da0e0..ef0b9c08f3bb4103fdb46c7d7f4bbe2f80a7b6bd 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 6cf29b94413c8fefc78f35a41db218a66c74ec15..0e552fde7ef5fd047aa1c3c806362336a7952d11 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 5e292ff8b2eee8b4244d71db332f8b08afbca58e..bbfc0125f46392067bd4c465d3e505c8ea5cf85b 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 6aa5f067ef3370bf979495238a13a97af34ffca6..6d4f20e557712855cee28c1129c44e52cc59ee56 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 eea77d55342d5d9e6378624fb7bbc41e2a1a9a47..796120eee457fa8dd9b3c5e493a17e9ecd658e5e 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 bf5a93ef30f6b7a395635c05a4a6caa0018cda14..6a1aa34b46dbc2492200867ef691ce1df97d98ef 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 8894b4fff44a74ac8e35c7f8190eb53a7feab136..10ef1bcd486682d9e6951344d54e2b1e6b08c0c7 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 4a8ee365bafd10a3ac430f6d27294dcb7eac6c40..edd47b0ab1e04ac29da9e52f9fee66399896d0a1 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 a3a72dc72803bacb4a04fd11eb3f29aa7d2256e6..af74f3e05290a014729a40a76f1509bcce440f29 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 56c5223ba3e5f03be549efb3c8400e2e55cb063a..8409cc5c00024cdf1963b7203743c51d3a47a98b 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 bde5a306b655c19e14c64680b3c4577654c67704..7f96ae22b6d8d52aa4315361208daa3a43c3030b 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 0000000000000000000000000000000000000000..13bff66459c14566084a212b2b60d7df31224dbc
--- /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 c1e6e891cde05194442ef34d7ae05d524664ac6f..25aa85efb5b89b58327ab3eb32069b8955161539 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 {
+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 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.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;
+ 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 socketWrite(loop: *std.event.Loop, fd: i32, buffer: []const u8) !void {
+
+/// 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) {
- 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.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 => return err,
+ else => @compileError("Unsupported OS"),
+ }
+ }
+}
+
+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);
+
+ 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) !std.os.File {
- var address = _address.*; // TODO https://github.com/ziglang/zig/issues/733
+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 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);
- try std.os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in));
+ 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 c10fdcbbe24d5131ff230a5fb332d4f4c16c63d0..3d20d8b9dcefef3d914a2844615942fe77fa97b3 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 7403c9699436ea7257bad441a77d5aed7c25539e..52241995275ece21ffae0add6aad535c7b30e988 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 8b76a3cb9e258506af9357dbacf33715ba1272ef..5c02f1ebe0a1c15d0245b7d859c45c237bc0b171 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 020a5dca54b78d2e5e82a8e1ffd4ffcfcef8ffd3..4a98dbcfa55b37e492c5b4454de1b478b9db49e5 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 a53d1d205007010e5e75c08ecc0c918da4cde503..778e3b965551a1cee33f18f4ac5af27147f946e4 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 6323c89ddabbb60455c20303dc1e74e65f443a81..e00c664afa56975d515a3c884e97217e5f5835d5 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 3bb6c9d58d5b1318c649bf9945dc66e47d24bb4e..6d23711949c885c183086f29d3aed460a7ce7d26 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 8cf237f634db232385bff74b8626af630b338c23..f227e02c7107d29203df97785a5fc35bee456223 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 2db33e5917447860286bb6343b9e59dfbcfab4df..6a9e8495bda00028c4d0135fd8ae62529097a786 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 efa9ad7657cafb79f4652ae3b9539ef823ec6925..401076d53d33b96f8689704fc310f0fdb3388c45 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 bcd9d15b9c740a292843a0e6b48ed698af85883d..554f85c168d32cfd1bbf1f1a36b4dc4d04fd2d9c 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 36b4f8bd4fa2d7821a5c0e3fe440756b3cc04008..adbc414909b923b500e1933c007f726f49be3323 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 88908e87758dc43e9b76e8cc0c39dd992884b52e..ec4dcd1f55a6f4d93328337bdd68105103e813e3 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;
--
2.54.0
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 ae0d67b2ec569b3cc1f458d568e48933774657a5..14cba3970ed9551fac0806b712262f547c5ba966 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 6e07ef571a70cbd430d3d0e669c86c829e4d48dc..38b85873c02be3e7b7025b143979f1bbb766f721 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 7f96ae22b6d8d52aa4315361208daa3a43c3030b..ba71677688a7ca760cfc69b05b6465e4cd639ebc 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 13bff66459c14566084a212b2b60d7df31224dbc..6bdec54c1bcf6f2e428814e2b519a8bdeefb7e50 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 4a98dbcfa55b37e492c5b4454de1b478b9db49e5..fcc626a8f2f5783ff149520144108f6b4aead7b6 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 778e3b965551a1cee33f18f4ac5af27147f946e4..5c9e6eee8250a275df6c8f7ba6698d99f9a71915 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 7d983421e0d929a1d9e5a12d9f9064ac46cbcaa8..6b5628760c67e9c3c67386ae1bfb55c7b5d53e0f 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,
--
2.54.0
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 | 41 ++++----
std/os/index.zig | 196 +++++++++++++++++++++------------------
std/os/test.zig | 21 +++++
7 files changed, 202 insertions(+), 140 deletions(-)
diff --git a/std/build.zig b/std/build.zig
index f9fed6ad2fd35bc51382585af6fb340220a095c2..cc12a75df5893e52a8a7e2265b3ecd93aa7399c4 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 6bdec54c1bcf6f2e428814e2b519a8bdeefb7e50..fa05c61abe2b9f7943ba90dbb61beff2125d8218 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 3d20d8b9dcefef3d914a2844615942fe77fa97b3..c22a8ca78beece2696379748200e2c9d9cc32726 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 5c02f1ebe0a1c15d0245b7d859c45c237bc0b171..8bfd3f89597828e751f112628815dc37d8f6e0f3 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 fcc626a8f2f5783ff149520144108f6b4aead7b6..f5e754cdc7831a1280fb7ca703b851f52783f422 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -102,12 +102,24 @@ pub const File = struct {
/// If a file already exists in the destination this returns OpenError.PathAlreadyExists
/// Call close to clean up.
pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
+ if (is_posix) {
+ 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);
+ } else {
+ @compileError("TODO implement openWriteMode for this OS");
+ }
+ }
+
+ 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.posixOpen(path, flags, file_mode);
+ const fd = try os.posixOpenC(path, flags, file_mode);
return openHandle(fd);
} else if (is_windows) {
- const path_w = try windows_util.sliceToPrefixedFileW(path);
+ const path_w = try windows_util.cStrToPrefixedFileW(path);
return openWriteNoClobberW(&path_w, file_mode);
} else {
@compileError("TODO implement openWriteMode for this OS");
@@ -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 5c9e6eee8250a275df6c8f7ba6698d99f9a71915..40219b9cfa68f249fbb5b2da594f2eb720abe29c 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 653ab13fd854668cc93983d405f5154a2a170b5b..5142920687105dcd534c109aaa163a39995b1813 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);
+}
--
2.54.0
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 a280c31f74d26fcc7fe6d6f9b3799a266e534a75..2b58f142669df881527fa8179facfc479f83329b 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) {
--
2.54.0
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 14cba3970ed9551fac0806b712262f547c5ba966..4f8b2f888058a486d9fb24f63b0043f22cb7cab7 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 fb7b536be923113b1210bf4c556b723b4954bb8a..3b1b4a2496617eeff60440695d37c8ea0b330581 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 {
--
2.54.0
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 2102da456c7a1b5613b6c61c366bd882351bbc64..e2ac5f6341daefd074e1131456f7a5218ba6fa0b 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,
--
2.54.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 2b58f142669df881527fa8179facfc479f83329b..e3753bff244a903cd913a8fc4ece036393f8ba6e 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));
--
2.54.0
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 40219b9cfa68f249fbb5b2da594f2eb720abe29c..b1356f8ed7209b1c0e8655264d936813ceb0706a 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 e00c664afa56975d515a3c884e97217e5f5835d5..8819aa21cd403ba8c26ed7e5460c00a21c6b66a2 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));
}
--
2.54.0
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 | 14 +++++-----
std/mutex.zig | 59 ++++++++++++++++++++++++++++++++++++++----
std/os/index.zig | 2 +-
std/os/linux/index.zig | 8 +++---
std/spinlock.zig | 32 +++++++++++++++++++++++
7 files changed, 106 insertions(+), 24 deletions(-)
create mode 100644 std/spinlock.zig
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 25c0dfa12628c1757808a68ba23e0bc6a3594350..c1ea43943d31b98d9c1301542fea17a70b10ba1f 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 e87e928049fc06e307eeb87f208712fb1622b3f3..aeb0f6377bc17979aa11320974d5b86c224b4c4f 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 ec627c9fc60b70b4276f6207d2a5c9dd8d922e2f..18489969df69c30ee3f7891d575cc8dbb67915ce 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 DynLib = @import("dynamic_library.zig").DynLib;
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 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 6aee87d1d797a73a0da9432bdadcd1ba39dbe968..9dc0c23d6d3f13ddc2a0cfbf9bf576b529366cce 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 b1356f8ed7209b1c0e8655264d936813ceb0706a..aee375405b80308a9568b8cc6db31e725edb8570 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 8819aa21cd403ba8c26ed7e5460c00a21c6b66a2..af61aeb8869336e57d815fd3f98b214d6dd70584 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 0000000000000000000000000000000000000000..75fdf9f6e1f67399607d62bd9bb4b2d316e78f4a
--- /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();
+}
--
2.54.0
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 9dc0c23d6d3f13ddc2a0cfbf9bf576b529366cce..e35bd81bc43250c9691463270d8f15a7d5072be3 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;
+ }
+}
--
2.54.0
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 cc737e344c4eed4ad86f7bfde35e059a57492576..8f34b45bbf3acad676b378e084bd852994c7ac72 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 f10466add336db6a70573af26e11dbd08fffc3a8..139babc7a8eba05a1392cc529e1a834cd13219a2 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;
--
2.54.0
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 30d941354acac4876443b7eb90dcff6bbe16cbda..d7071590d8218e34af591e374191100012accfee 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 4f8b2f888058a486d9fb24f63b0043f22cb7cab7..42737a22e554285de2860d77a1fc33cda507aca4 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 de69b53388c47e46b95c338af6923466e8411344..e792fd77aa8b2b3d6d578fef019268e84c3d742d 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 abdb3a24a3f0329f9a30e9d53f9a2176be4b7976..09d6fca7e71e8b32a198cc6034276706ee8493d5 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;
--
2.54.0
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 c1ea43943d31b98d9c1301542fea17a70b10ba1f..cff70950def4f7d4cc593763f2830d0853864354 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 09d6fca7e71e8b32a198cc6034276706ee8493d5..c48b56255d1c6dabe4da7c1b177d0733bc81e7a2 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;
}
--
2.54.0
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 | 193 +++++++++++++++++++++++++++++---------------
1 file changed, 130 insertions(+), 63 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 3485fda8150b78154122328fff4a17d0c7aaacd6..ad69e6757833a3fc032c33bdbdb2d8b14b0c3f83 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);
}
+ {#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;
-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);
+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#}
--
2.54.0
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 ad69e6757833a3fc032c33bdbdb2d8b14b0c3f83..891e14d8f1b152011583cb9fa3897897156f1a2e 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#}.