aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnthony Arian <anthonyarian96@gmail.com>2020-07-20 10:25:54 +0100
committerAnthony Arian <anthonyarian96@gmail.com>2020-07-20 10:25:54 +0100
commit3658dd5e89cd16c011bdc52d334c1308f440157b (patch)
tree09564ab2db65acc4a52d82bccbf0eb572fbc865f /src
parent68fe3e116d9c4bde67df990b8e0cbb3e70fc98b2 (diff)
parent596ca6cf70cf43c27e31bbcfc36bcdc70b13897a (diff)
downloadzig-3658dd5e89cd16c011bdc52d334c1308f440157b.tar.gz
zig-3658dd5e89cd16c011bdc52d334c1308f440157b.zip
Merge branch 'master' of https://github.com/ziglang/zig into 5002-fix-entrypoint-with-winmain
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp29
-rw-r--r--src/analyze.cpp54
-rw-r--r--src/analyze.hpp5
-rw-r--r--src/ast_render.cpp16
-rw-r--r--src/codegen.cpp47
-rw-r--r--src/compiler.cpp8
-rw-r--r--src/hash_map.hpp432
-rw-r--r--src/ir.cpp728
-rw-r--r--src/ir_print.cpp118
-rw-r--r--src/list.hpp3
-rw-r--r--src/os.cpp242
-rw-r--r--src/os.hpp8
-rw-r--r--src/parser.cpp28
-rw-r--r--src/softfloat_ext.cpp25
-rw-r--r--src/softfloat_ext.hpp9
-rw-r--r--src/tokenizer.cpp2
-rw-r--r--src/tokenizer.hpp1
-rw-r--r--src/util.hpp2
18 files changed, 1347 insertions, 410 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 9413ea73a4..a73efe2c82 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -692,7 +692,7 @@ enum NodeType {
NodeTypeSuspend,
NodeTypeAnyFrameType,
NodeTypeEnumLiteral,
- NodeTypeVarFieldType,
+ NodeTypeAnyTypeField,
};
enum FnInline {
@@ -705,7 +705,7 @@ struct AstNodeFnProto {
Buf *name;
ZigList<AstNode *> params;
AstNode *return_type;
- Token *return_var_token;
+ Token *return_anytype_token;
AstNode *fn_def_node;
// populated if this is an extern declaration
Buf *lib_name;
@@ -734,7 +734,7 @@ struct AstNodeFnDef {
struct AstNodeParamDecl {
Buf *name;
AstNode *type;
- Token *var_token;
+ Token *anytype_token;
Buf doc_comments;
bool is_noalias;
bool is_comptime;
@@ -1827,6 +1827,7 @@ enum BuiltinFnId {
BuiltinFnIdBitSizeof,
BuiltinFnIdWasmMemorySize,
BuiltinFnIdWasmMemoryGrow,
+ BuiltinFnIdSrc,
};
struct BuiltinFnEntry {
@@ -2144,7 +2145,7 @@ struct CodeGen {
ZigType *entry_num_lit_float;
ZigType *entry_undef;
ZigType *entry_null;
- ZigType *entry_var;
+ ZigType *entry_anytype;
ZigType *entry_global_error_set;
ZigType *entry_enum_literal;
ZigType *entry_any_frame;
@@ -2640,6 +2641,7 @@ enum IrInstSrcId {
IrInstSrcIdCall,
IrInstSrcIdCallArgs,
IrInstSrcIdCallExtra,
+ IrInstSrcIdAsyncCallExtra,
IrInstSrcIdConst,
IrInstSrcIdReturn,
IrInstSrcIdContainerInitList,
@@ -2754,6 +2756,7 @@ enum IrInstSrcId {
IrInstSrcIdSpillEnd,
IrInstSrcIdWasmMemorySize,
IrInstSrcIdWasmMemoryGrow,
+ IrInstSrcIdSrc,
};
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
@@ -3253,6 +3256,20 @@ struct IrInstSrcCallExtra {
ResultLoc *result_loc;
};
+// This is a pass1 instruction, used by @asyncCall, when the args node
+// is not a literal.
+// `args` is expected to be either a struct or a tuple.
+struct IrInstSrcAsyncCallExtra {
+ IrInstSrc base;
+
+ CallModifier modifier;
+ IrInstSrc *fn_ref;
+ IrInstSrc *ret_ptr;
+ IrInstSrc *new_stack;
+ IrInstSrc *args;
+ ResultLoc *result_loc;
+};
+
struct IrInstGenCall {
IrInstGen base;
@@ -3761,6 +3778,10 @@ struct IrInstGenWasmMemoryGrow {
IrInstGen *delta;
};
+struct IrInstSrcSrc {
+ IrInstSrc base;
+};
+
struct IrInstSrcSlice {
IrInstSrc base;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 9062c1fb13..66f3f28b50 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1129,7 +1129,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *
ZigValue *result = g->pass1_arena->create<ZigValue>();
ZigValue *result_ptr = g->pass1_arena->create<ZigValue>();
result->special = ConstValSpecialUndef;
- result->type = (type_entry == nullptr) ? g->builtin_types.entry_var : type_entry;
+ result->type = (type_entry == nullptr) ? g->builtin_types.entry_anytype : type_entry;
result_ptr->special = ConstValSpecialStatic;
result_ptr->type = get_pointer_to_type(g, result->type, false);
result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar;
@@ -1230,7 +1230,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_opaque_type) {
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
- if (type_val->data.x_type == g->builtin_types.entry_var) {
+ if (type_val->data.x_type == g->builtin_types.entry_anytype) {
*is_opaque_type = false;
return ErrorNone;
}
@@ -1511,13 +1511,13 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
}
for (; i < fn_type_id->param_count; i += 1) {
const char *comma_str = (i == 0) ? "" : ",";
- buf_appendf(&fn_type->name, "%svar", comma_str);
+ buf_appendf(&fn_type->name, "%sanytype", comma_str);
}
buf_append_str(&fn_type->name, ")");
if (fn_type_id->cc != CallingConventionUnspecified) {
buf_appendf(&fn_type->name, " callconv(.%s)", calling_convention_name(fn_type_id->cc));
}
- buf_append_str(&fn_type->name, " var");
+ buf_append_str(&fn_type->name, " anytype");
fn_type->data.fn.fn_type_id = *fn_type_id;
fn_type->data.fn.is_generic = true;
@@ -1853,10 +1853,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
buf_sprintf("var args only allowed in functions with C calling convention"));
return g->builtin_types.entry_invalid;
}
- } else if (param_node->data.param_decl.var_token != nullptr) {
+ } else if (param_node->data.param_decl.anytype_token != nullptr) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
add_node_error(g, param_node,
- buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
+ buf_sprintf("parameter of type 'anytype' not allowed in function with calling convention '%s'",
calling_convention_name(fn_type_id.cc)));
return g->builtin_types.entry_invalid;
}
@@ -1942,10 +1942,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
fn_entry->align_bytes = fn_type_id.alignment;
}
- if (fn_proto->return_var_token != nullptr) {
+ if (fn_proto->return_anytype_token != nullptr) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
add_node_error(g, fn_proto->return_type,
- buf_sprintf("return type 'var' not allowed in function with calling convention '%s'",
+ buf_sprintf("return type 'anytype' not allowed in function with calling convention '%s'",
calling_convention_name(fn_type_id.cc)));
return g->builtin_types.entry_invalid;
}
@@ -3802,7 +3802,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeEnumLiteral:
case NodeTypeAnyFrameType:
case NodeTypeErrorSetField:
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
zig_unreachable();
}
}
@@ -3823,15 +3823,18 @@ static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
}
}
-ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry) {
+ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
return g->builtin_types.entry_invalid;
+ case ZigTypeIdOpaque:
+ if (source_node->is_extern)
+ return type_entry;
+ ZIG_FALLTHROUGH;
case ZigTypeIdUnreachable:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
- case ZigTypeIdOpaque:
- add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
+ add_node_error(g, source_node->type, buf_sprintf("variable of type '%s' not allowed",
buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
case ZigTypeIdComptimeFloat:
@@ -3973,7 +3976,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
} else {
tld_var->analyzing_type = true;
ZigType *proposed_type = analyze_type_expr(g, tld_var->base.parent_scope, var_decl->type);
- explicit_type = validate_var_type(g, var_decl->type, proposed_type);
+ explicit_type = validate_var_type(g, var_decl, proposed_type);
}
}
@@ -4012,6 +4015,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
} else if (!is_extern) {
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
implicit_type = g->builtin_types.entry_invalid;
+ } else if (explicit_type == nullptr) {
+ // extern variable without explicit type
+ add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
+ implicit_type = g->builtin_types.entry_invalid;
}
ZigType *type = explicit_type ? explicit_type : implicit_type;
@@ -5864,7 +5871,7 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
Error err;
- if (ty == g->builtin_types.entry_var) {
+ if (ty == g->builtin_types.entry_anytype) {
return ReqCompTimeYes;
}
switch (ty->id) {
@@ -6012,6 +6019,19 @@ ZigValue *create_const_null(CodeGen *g, ZigType *type) {
return const_val;
}
+void init_const_fn(ZigValue *const_val, ZigFn *fn) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->type = fn->type_entry;
+ const_val->data.x_ptr.special = ConstPtrSpecialFunction;
+ const_val->data.x_ptr.data.fn.fn_entry = fn;
+}
+
+ZigValue *create_const_fn(CodeGen *g, ZigFn *fn) {
+ ZigValue *const_val = g->pass1_arena->create<ZigValue>();
+ init_const_fn(const_val, fn);
+ return const_val;
+}
+
void init_const_float(ZigValue *const_val, ZigType *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
@@ -9584,6 +9604,12 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
break;
}
}
+ } else if (dest->type->id == ZigTypeIdUnion) {
+ bigint_init_bigint(&dest->data.x_union.tag, &src->data.x_union.tag);
+ dest->data.x_union.payload = g->pass1_arena->create<ZigValue>();
+ copy_const_val(g, dest->data.x_union.payload, src->data.x_union.payload);
+ dest->data.x_union.payload->parent.id = ConstParentIdUnion;
+ dest->data.x_union.payload->parent.data.p_union.union_val = dest;
} else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
dest->data.x_optional = g->pass1_arena->create<ZigValue>();
copy_const_val(g, dest->data.x_optional, src->data.x_optional);
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 5899db8a64..cb58aa6b74 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -77,7 +77,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all
ZigType *get_src_ptr_type(ZigType *type);
uint32_t get_ptr_align(CodeGen *g, ZigType *type);
bool get_ptr_const(CodeGen *g, ZigType *type);
-ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
+ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry);
ZigType *container_ref_type(ZigType *type_entry);
bool type_is_complete(ZigType *type_entry);
bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
@@ -180,6 +180,9 @@ ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size
void init_const_null(ZigValue *const_val, ZigType *type);
ZigValue *create_const_null(CodeGen *g, ZigType *type);
+void init_const_fn(ZigValue *const_val, ZigFn *fn);
+ZigValue *create_const_fn(CodeGen *g, ZigFn *fn);
+
ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count);
ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count);
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 49fad80a40..ad308bf416 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -270,8 +270,8 @@ static const char *node_type_str(NodeType node_type) {
return "EnumLiteral";
case NodeTypeErrorSetField:
return "ErrorSetField";
- case NodeTypeVarFieldType:
- return "VarFieldType";
+ case NodeTypeAnyTypeField:
+ return "AnyTypeField";
}
zig_unreachable();
}
@@ -466,8 +466,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
}
if (param_decl->data.param_decl.is_var_args) {
fprintf(ar->f, "...");
- } else if (param_decl->data.param_decl.var_token != nullptr) {
- fprintf(ar->f, "var");
+ } else if (param_decl->data.param_decl.anytype_token != nullptr) {
+ fprintf(ar->f, "anytype");
} else {
render_node_grouped(ar, param_decl->data.param_decl.type);
}
@@ -496,8 +496,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, ")");
}
- if (node->data.fn_proto.return_var_token != nullptr) {
- fprintf(ar->f, "var");
+ if (node->data.fn_proto.return_anytype_token != nullptr) {
+ fprintf(ar->f, "anytype");
} else {
AstNode *return_type_node = node->data.fn_proto.return_type;
assert(return_type_node != nullptr);
@@ -1216,8 +1216,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));
break;
}
- case NodeTypeVarFieldType: {
- fprintf(ar->f, "var");
+ case NodeTypeAnyTypeField: {
+ fprintf(ar->f, "anytype");
break;
}
case NodeTypeParamDecl:
diff --git a/src/codegen.cpp b/src/codegen.cpp
index f945dd6545..3473a2b0ac 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1535,9 +1535,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
zig_unreachable();
}
- if (actual_type->id == ZigTypeIdInt &&
- !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
- want_runtime_safety)
+ if (actual_type->id == ZigTypeIdInt && want_runtime_safety && (
+ // negative to unsigned
+ (!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed) ||
+ // unsigned would become negative
+ (wanted_type->data.integral.is_signed && !actual_type->data.integral.is_signed && actual_bits == wanted_bits)))
{
LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type));
LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");
@@ -1547,7 +1549,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
LLVMPositionBuilderAtEnd(g->builder, fail_block);
- gen_safety_crash(g, PanicMsgIdCastNegativeToUnsigned);
+ gen_safety_crash(g, actual_type->data.integral.is_signed ? PanicMsgIdCastNegativeToUnsigned : PanicMsgIdCastTruncatedData);
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
@@ -3540,7 +3542,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl
for (size_t field_i = 0; field_i < field_count; field_i += 1) {
TypeEnumField *type_enum_field = &wanted_type->data.enumeration.fields[field_i];
-
+
Buf *name = type_enum_field->name;
auto entry = occupied_tag_values.put_unique(type_enum_field->value, name);
if (entry != nullptr) {
@@ -3654,7 +3656,7 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper
} else if (scalar_type->data.integral.is_signed) {
return LLVMBuildNSWNeg(g->builder, llvm_operand, "");
} else {
- return LLVMBuildNUWNeg(g->builder, llvm_operand, "");
+ zig_unreachable();
}
} else {
zig_unreachable();
@@ -3984,7 +3986,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable,
assert(array_type->data.pointer.child_type->id == ZigTypeIdArray);
array_type = array_type->data.pointer.child_type;
}
-
+
assert(array_type->data.array.len != 0 || array_type->data.array.sentinel != nullptr);
if (safety_check_on) {
@@ -5258,7 +5260,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
for (size_t field_i = 0; field_i < field_count; field_i += 1) {
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
-
+
Buf *name = type_enum_field->name;
auto entry = occupied_tag_values.put_unique(type_enum_field->value, name);
if (entry != nullptr) {
@@ -5471,7 +5473,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) {
}
auto bit_count = operand_type->data.integral.bit_count;
bool is_signed = operand_type->data.integral.is_signed;
-
+
ir_assert(bit_count != 0, instruction);
if (bit_count == 1 || !is_power_of_2(bit_count)) {
return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8));
@@ -5583,8 +5585,12 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, Ir
bool val_is_undef = value_is_all_undef(g, instruction->byte->value);
LLVMValueRef fill_char;
- if (val_is_undef && ir_want_runtime_safety_scope(g, instruction->base.base.scope)) {
- fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
+ if (val_is_undef) {
+ if (ir_want_runtime_safety_scope(g, instruction->base.base.scope)) {
+ fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
+ } else {
+ return nullptr;
+ }
} else {
fill_char = ir_llvm_value(g, instruction->byte);
}
@@ -7473,6 +7479,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
continue;
}
ZigValue *field_val = const_val->data.x_struct.fields[i];
+ if (field_val == nullptr) {
+ add_node_error(g, type_struct_field->decl_node,
+ buf_sprintf("compiler bug: generating const value for struct field '%s'",
+ buf_ptr(type_struct_field->name)));
+ codegen_report_errors_and_exit(g);
+ }
ZigType *field_type = field_val->type;
assert(field_type != nullptr);
if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, field_type))) {
@@ -8436,8 +8448,8 @@ static void define_builtin_types(CodeGen *g) {
}
{
ZigType *entry = new_type_table_entry(ZigTypeIdOpaque);
- buf_init_from_str(&entry->name, "(var)");
- g->builtin_types.entry_var = entry;
+ buf_init_from_str(&entry->name, "(anytype)");
+ g->builtin_types.entry_anytype = entry;
}
for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
@@ -8714,6 +8726,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1);
create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
+ create_builtin_fn(g, BuiltinFnIdSrc, "src", 0);
}
static const char *bool_to_str(bool b) {
@@ -9264,7 +9277,7 @@ static void init(CodeGen *g) {
abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32" : "lp64";
}
}
-
+
g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
target_specific_cpu_args, target_specific_features, opt_level, reloc_mode,
to_llvm_code_model(g), g->function_sections, float_abi, abi_name);
@@ -9464,9 +9477,15 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
const char *libcxx_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxx" OS_SEP "include",
buf_ptr(g->zig_lib_dir)));
+ const char *libcxxabi_include_path = buf_ptr(buf_sprintf("%s" OS_SEP "libcxxabi" OS_SEP "include",
+ buf_ptr(g->zig_lib_dir)));
+
args.append("-isystem");
args.append(libcxx_include_path);
+ args.append("-isystem");
+ args.append(libcxxabi_include_path);
+
if (target_abi_is_musl(g->zig_target->abi)) {
args.append("-D_LIBCPP_HAS_MUSL_LIBC");
}
diff --git a/src/compiler.cpp b/src/compiler.cpp
index 8294fc7871..6c477a1506 100644
--- a/src/compiler.cpp
+++ b/src/compiler.cpp
@@ -38,11 +38,19 @@ Error get_compiler_id(Buf **result) {
ZigList<Buf *> lib_paths = {};
if ((err = os_self_exe_shared_libs(lib_paths)))
return err;
+ #if defined(ZIG_OS_DARWIN)
+ // only add the self exe path on mac os
+ Buf *lib_path = lib_paths.at(0);
+ if ((err = cache_add_file(ch, lib_path)))
+ return err;
+ #else
for (size_t i = 0; i < lib_paths.length; i += 1) {
Buf *lib_path = lib_paths.at(i);
if ((err = cache_add_file(ch, lib_path)))
return err;
}
+ #endif
+
if ((err = cache_final(ch, &saved_compiler_id)))
return err;
diff --git a/src/hash_map.hpp b/src/hash_map.hpp
index 69e5568093..8681e5b761 100644
--- a/src/hash_map.hpp
+++ b/src/hash_map.hpp
@@ -19,45 +19,85 @@ public:
init_capacity(capacity);
}
void deinit(void) {
- heap::c_allocator.deallocate(_entries, _capacity);
+ _entries.deinit();
+ heap::c_allocator.deallocate(_index_bytes,
+ _indexes_len * capacity_index_size(_indexes_len));
}
struct Entry {
+ uint32_t hash;
+ uint32_t distance_from_start_index;
K key;
V value;
- bool used;
- int distance_from_start_index;
};
void clear() {
- for (int i = 0; i < _capacity; i += 1) {
- _entries[i].used = false;
- }
- _size = 0;
+ _entries.clear();
+ memset(_index_bytes, 0, _indexes_len * capacity_index_size(_indexes_len));
_max_distance_from_start_index = 0;
_modification_count += 1;
}
- int size() const {
- return _size;
+ size_t size() const {
+ return _entries.length;
}
void put(const K &key, const V &value) {
_modification_count += 1;
- internal_put(key, value);
-
- // if we get too full (60%), double the capacity
- if (_size * 5 >= _capacity * 3) {
- Entry *old_entries = _entries;
- int old_capacity = _capacity;
- init_capacity(_capacity * 2);
- // dump all of the old elements into the new table
- for (int i = 0; i < old_capacity; i += 1) {
- Entry *old_entry = &old_entries[i];
- if (old_entry->used)
- internal_put(old_entry->key, old_entry->value);
+
+ // This allows us to take a pointer to an entry in `internal_put` which
+ // will not become a dead pointer when the array list is appended.
+ _entries.ensure_capacity(_entries.length + 1);
+
+ if (_index_bytes == nullptr) {
+ if (_entries.length < 16) {
+ _entries.append({HashFunction(key), 0, key, value});
+ return;
+ } else {
+ _indexes_len = 32;
+ _index_bytes = heap::c_allocator.allocate<uint8_t>(_indexes_len);
+ _max_distance_from_start_index = 0;
+ for (size_t i = 0; i < _entries.length; i += 1) {
+ Entry *entry = &_entries.items[i];
+ put_index(entry, i, _index_bytes);
+ }
+ return internal_put(key, value, _index_bytes);
+ }
+ }
+
+ // if we would get too full (60%), double the indexes size
+ if ((_entries.length + 1) * 5 >= _indexes_len * 3) {
+ heap::c_allocator.deallocate(_index_bytes,
+ _indexes_len * capacity_index_size(_indexes_len));
+ _indexes_len *= 2;
+ size_t sz = capacity_index_size(_indexes_len);
+ // This zero initializes the bytes, setting them all empty.
+ _index_bytes = heap::c_allocator.allocate<uint8_t>(_indexes_len * sz);
+ _max_distance_from_start_index = 0;
+ for (size_t i = 0; i < _entries.length; i += 1) {
+ Entry *entry = &_entries.items[i];
+ switch (sz) {
+ case 1:
+ put_index(entry, i, (uint8_t*)_index_bytes);
+ continue;
+ case 2:
+ put_index(entry, i, (uint16_t*)_index_bytes);
+ continue;
+ case 4:
+ put_index(entry, i, (uint32_t*)_index_bytes);
+ continue;
+ default:
+ put_index(entry, i, (size_t*)_index_bytes);
+ continue;
+ }
}
- heap::c_allocator.deallocate(old_entries, old_capacity);
+ }
+
+ switch (capacity_index_size(_indexes_len)) {
+ case 1: return internal_put(key, value, (uint8_t*)_index_bytes);
+ case 2: return internal_put(key, value, (uint16_t*)_index_bytes);
+ case 4: return internal_put(key, value, (uint32_t*)_index_bytes);
+ default: return internal_put(key, value, (size_t*)_index_bytes);
}
}
@@ -81,40 +121,31 @@ public:
return internal_get(key);
}
- void maybe_remove(const K &key) {
- if (maybe_get(key)) {
- remove(key);
- }
+ bool remove(const K &key) {
+ bool deleted_something = maybe_remove(key);
+ if (!deleted_something)
+ zig_panic("key not found");
+ return deleted_something;
}
- void remove(const K &key) {
+ bool maybe_remove(const K &key) {
_modification_count += 1;
- int start_index = key_to_index(key);
- for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
- int index = (start_index + roll_over) % _capacity;
- Entry *entry = &_entries[index];
-
- if (!entry->used)
- zig_panic("key not found");
-
- if (!EqualFn(entry->key, key))
- continue;
-
- for (; roll_over < _capacity; roll_over += 1) {
- int next_index = (start_index + roll_over + 1) % _capacity;
- Entry *next_entry = &_entries[next_index];
- if (!next_entry->used || next_entry->distance_from_start_index == 0) {
- entry->used = false;
- _size -= 1;
- return;
+ if (_index_bytes == nullptr) {
+ uint32_t hash = HashFunction(key);
+ for (size_t i = 0; i < _entries.length; i += 1) {
+ if (_entries.items[i].hash == hash && EqualFn(_entries.items[i].key, key)) {
+ _entries.swap_remove(i);
+ return true;
}
- *entry = *next_entry;
- entry->distance_from_start_index -= 1;
- entry = next_entry;
}
- zig_panic("shifting everything in the table");
+ return false;
+ }
+ switch (capacity_index_size(_indexes_len)) {
+ case 1: return internal_remove(key, (uint8_t*)_index_bytes);
+ case 2: return internal_remove(key, (uint16_t*)_index_bytes);
+ case 4: return internal_remove(key, (uint32_t*)_index_bytes);
+ default: return internal_remove(key, (size_t*)_index_bytes);
}
- zig_panic("key not found");
}
class Iterator {
@@ -122,24 +153,16 @@ public:
Entry *next() {
if (_inital_modification_count != _table->_modification_count)
zig_panic("concurrent modification");
- if (_count >= _table->size())
- return NULL;
- for (; _index < _table->_capacity; _index += 1) {
- Entry *entry = &_table->_entries[_index];
- if (entry->used) {
- _index += 1;
- _count += 1;
- return entry;
- }
- }
- zig_panic("no next item");
+ if (_index >= _table->_entries.length)
+ return nullptr;
+ Entry *entry = &_table->_entries.items[_index];
+ _index += 1;
+ return entry;
}
private:
const HashMap * _table;
- // how many items have we returned
- int _count = 0;
// iterator through the entry array
- int _index = 0;
+ size_t _index = 0;
// used to detect concurrent modification
uint32_t _inital_modification_count;
Iterator(const HashMap * table) :
@@ -154,89 +177,244 @@ public:
}
private:
-
- Entry *_entries;
- int _capacity;
- int _size;
- int _max_distance_from_start_index;
- // this is used to detect bugs where a hashtable is edited while an iterator is running.
+ // Maintains insertion order.
+ ZigList<Entry> _entries;
+ // If _indexes_len is less than 2**8, this is an array of uint8_t.
+ // If _indexes_len is less than 2**16, it is an array of uint16_t.
+ // If _indexes_len is less than 2**32, it is an array of uint32_t.
+ // Otherwise it is size_t.
+ // It's off by 1. 0 means empty slot, 1 means index 0, etc.
+ uint8_t *_index_bytes;
+ // This is the number of indexes. When indexes are bytes, it equals number of bytes.
+ // When indexes are uint16_t, _indexes_len is half the number of bytes.
+ size_t _indexes_len;
+
+ size_t _max_distance_from_start_index;
+ // This is used to detect bugs where a hashtable is edited while an iterator is running.
uint32_t _modification_count;
- void init_capacity(int capacity) {
- _capacity = capacity;
- _entries = heap::c_allocator.allocate<Entry>(_capacity);
- _size = 0;
- _max_distance_from_start_index = 0;
- for (int i = 0; i < _capacity; i += 1) {
- _entries[i].used = false;
+ void init_capacity(size_t capacity) {
+ _entries = {};
+ _entries.ensure_capacity(capacity);
+ _indexes_len = 0;
+ if (capacity >= 16) {
+ // So that at capacity it will only be 60% full.
+ _indexes_len = capacity * 5 / 3;
+ size_t sz = capacity_index_size(_indexes_len);
+ // This zero initializes _index_bytes which sets them all to empty.
+ _index_bytes = heap::c_allocator.allocate<uint8_t>(_indexes_len * sz);
+ } else {
+ _index_bytes = nullptr;
}
+
+ _max_distance_from_start_index = 0;
+ _modification_count = 0;
}
- void internal_put(K key, V value) {
- int start_index = key_to_index(key);
- for (int roll_over = 0, distance_from_start_index = 0;
- roll_over < _capacity; roll_over += 1, distance_from_start_index += 1)
+ static size_t capacity_index_size(size_t len) {
+ if (len < UINT8_MAX)
+ return 1;
+ if (len < UINT16_MAX)
+ return 2;
+ if (len < UINT32_MAX)
+ return 4;
+ return sizeof(size_t);
+ }
+
+ template <typename I>
+ void internal_put(const K &key, const V &value, I *indexes) {
+ uint32_t hash = HashFunction(key);
+ uint32_t distance_from_start_index = 0;
+ size_t start_index = hash_to_index(hash);
+ for (size_t roll_over = 0; roll_over < _indexes_len;
+ roll_over += 1, distance_from_start_index += 1)
{
- int index = (start_index + roll_over) % _capacity;
- Entry *entry = &_entries[index];
-
- if (entry->used && !EqualFn(entry->key, key)) {
- if (entry->distance_from_start_index < distance_from_start_index) {
- // robin hood to the rescue
- Entry tmp = *entry;
- if (distance_from_start_index > _max_distance_from_start_index)
- _max_distance_from_start_index = distance_from_start_index;
- *entry = {
- key,
- value,
- true,
- distance_from_start_index,
- };
- key = tmp.key;
- value = tmp.value;
- distance_from_start_index = tmp.distance_from_start_index;
+ size_t index_index = (start_index + roll_over) % _indexes_len;
+ I index_data = indexes[index_index];
+ if (index_data == 0) {
+ _entries.append_assuming_capacity({ hash, distance_from_start_index, key, value });
+ indexes[index_index] = _entries.length;
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+ return;
+ }
+ // This pointer survives the following append because we call
+ // _entries.ensure_capacity before internal_put.
+ Entry *entry = &_entries.items[index_data - 1];
+ if (entry->hash == hash && EqualFn(entry->key, key)) {
+ *entry = {hash, distance_from_start_index, key, value};
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+ return;
+ }
+ if (entry->distance_from_start_index < distance_from_start_index) {
+ // In this case, we did not find the item. We will put a new entry.
+ // However, we will use this index for the new entry, and move
+ // the previous index down the line, to keep the _max_distance_from_start_index
+ // as small as possible.
+ _entries.append_assuming_capacity({ hash, distance_from_start_index, key, value });
+ indexes[index_index] = _entries.length;
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+
+ distance_from_start_index = entry->distance_from_start_index;
+
+ // Find somewhere to put the index we replaced by shifting
+ // following indexes backwards.
+ roll_over += 1;
+ distance_from_start_index += 1;
+ for (; roll_over < _indexes_len; roll_over += 1, distance_from_start_index += 1) {
+ size_t index_index = (start_index + roll_over) % _indexes_len;
+ I next_index_data = indexes[index_index];
+ if (next_index_data == 0) {
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+ entry->distance_from_start_index = distance_from_start_index;
+ indexes[index_index] = index_data;
+ return;
+ }
+ Entry *next_entry = &_entries.items[next_index_data - 1];
+ if (next_entry->distance_from_start_index < distance_from_start_index) {
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+ entry->distance_from_start_index = distance_from_start_index;
+ indexes[index_index] = index_data;
+ distance_from_start_index = next_entry->distance_from_start_index;
+ entry = next_entry;
+ index_data = next_index_data;
+ }
}
- continue;
+ zig_unreachable();
+ }
+ }
+ zig_unreachable();
+ }
+
+ template <typename I>
+ void put_index(Entry *entry, size_t entry_index, I *indexes) {
+ size_t start_index = hash_to_index(entry->hash);
+ size_t index_data = entry_index + 1;
+ for (size_t roll_over = 0, distance_from_start_index = 0;
+ roll_over < _indexes_len; roll_over += 1, distance_from_start_index += 1)
+ {
+ size_t index_index = (start_index + roll_over) % _indexes_len;
+ size_t next_index_data = indexes[index_index];
+ if (next_index_data == 0) {
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+ entry->distance_from_start_index = distance_from_start_index;
+ indexes[index_index] = index_data;
+ return;
+ }
+ Entry *next_entry = &_entries.items[next_index_data - 1];
+ if (next_entry->distance_from_start_index < distance_from_start_index) {
+ if (distance_from_start_index > _max_distance_from_start_index)
+ _max_distance_from_start_index = distance_from_start_index;
+ entry->distance_from_start_index = distance_from_start_index;
+ indexes[index_index] = index_data;
+ distance_from_start_index = next_entry->distance_from_start_index;
+ entry = next_entry;
+ index_data = next_index_data;
}
+ }
+ zig_unreachable();
+ }
- if (!entry->used) {
- // adding an entry. otherwise overwriting old value with
- // same key
- _size += 1;
+ Entry *internal_get(const K &key) const {
+ if (_index_bytes == nullptr) {
+ uint32_t hash = HashFunction(key);
+ for (size_t i = 0; i < _entries.length; i += 1) {
+ if (_entries.items[i].hash == hash && EqualFn(_entries.items[i].key, key)) {
+ return &_entries.items[i];
+ }
}
+ return nullptr;
+ }
+ switch (capacity_index_size(_indexes_len)) {
+ case 1: return internal_get2(key, (uint8_t*)_index_bytes);
+ case 2: return internal_get2(key, (uint16_t*)_index_bytes);
+ case 4: return internal_get2(key, (uint32_t*)_index_bytes);
+ default: return internal_get2(key, (size_t*)_index_bytes);
+ }
+ }
- if (distance_from_start_index > _max_distance_from_start_index)
- _max_distance_from_start_index = distance_from_start_index;
- *entry = {
- key,
- value,
- true,
- distance_from_start_index,
- };
- return;
+ template <typename I>
+ Entry *internal_get2(const K &key, I *indexes) const {
+ uint32_t hash = HashFunction(key);
+ size_t start_index = hash_to_index(hash);
+ for (size_t roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
+ size_t index_index = (start_index + roll_over) % _indexes_len;
+ size_t index_data = indexes[index_index];
+ if (index_data == 0)
+ return nullptr;
+
+ Entry *entry = &_entries.items[index_data - 1];
+ if (entry->hash == hash && EqualFn(entry->key, key))
+ return entry;
}
- zig_panic("put into a full HashMap");
+ return nullptr;
}
+ size_t hash_to_index(uint32_t hash) const {
+ return ((size_t)hash) % _indexes_len;
+ }
- Entry *internal_get(const K &key) const {
- int start_index = key_to_index(key);
- for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
- int index = (start_index + roll_over) % _capacity;
- Entry *entry = &_entries[index];
+ template <typename I>
+ bool internal_remove(const K &key, I *indexes) {
+ uint32_t hash = HashFunction(key);
+ size_t start_index = hash_to_index(hash);
+ for (size_t roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
+ size_t index_index = (start_index + roll_over) % _indexes_len;
+ size_t index_data = indexes[index_index];
+ if (index_data == 0)
+ return false;
+
+ size_t index = index_data - 1;
+ Entry *entry = &_entries.items[index];
+ if (entry->hash != hash || !EqualFn(entry->key, key))
+ continue;
- if (!entry->used)
- return NULL;
+ size_t prev_index = index_index;
+ _entries.swap_remove(index);
+ if (_entries.length > 0 && _entries.length != index) {
+ // Because of the swap remove, now we need to update the index that was
+ // pointing to the last entry and is now pointing to this removed item slot.
+ update_entry_index(_entries.length, index, indexes);
+ }
- if (EqualFn(entry->key, key))
- return entry;
+ // Now we have to shift over the following indexes.
+ roll_over += 1;
+ for (; roll_over < _indexes_len; roll_over += 1) {
+ size_t next_index = (start_index + roll_over) % _indexes_len;
+ if (indexes[next_index] == 0) {
+ indexes[prev_index] = 0;
+ return true;
+ }
+ Entry *next_entry = &_entries.items[indexes[next_index] - 1];
+ if (next_entry->distance_from_start_index == 0) {
+ indexes[prev_index] = 0;
+ return true;
+ }
+ indexes[prev_index] = indexes[next_index];
+ prev_index = next_index;
+ next_entry->distance_from_start_index -= 1;
+ }
+ zig_unreachable();
}
- return NULL;
+ return false;
}
- int key_to_index(const K &key) const {
- return (int)(HashFunction(key) % ((uint32_t)_capacity));
+ template <typename I>
+ void update_entry_index(size_t old_entry_index, size_t new_entry_index, I *indexes) {
+ size_t start_index = hash_to_index(_entries.items[new_entry_index].hash);
+ for (size_t roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) {
+ size_t index_index = (start_index + roll_over) % _indexes_len;
+ if (indexes[index_index] == old_entry_index + 1) {
+ indexes[index_index] = new_entry_index + 1;
+ return;
+ }
+ }
+ zig_unreachable();
}
};
-
#endif
diff --git a/src/ir.cpp b/src/ir.cpp
index 887f0a2f9b..11ff7746e7 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -13,6 +13,7 @@
#include "os.hpp"
#include "range_set.hpp"
#include "softfloat.hpp"
+#include "softfloat_ext.hpp"
#include "util.hpp"
#include "mem_list.hpp"
#include "all_types.hpp"
@@ -286,6 +287,7 @@ static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* so
IrInstGen *struct_operand, TypeStructField *field);
static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right);
static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right);
+static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field);
#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
#define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
@@ -308,6 +310,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCall *>(inst));
case IrInstSrcIdCallExtra:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallExtra *>(inst));
+ case IrInstSrcIdAsyncCallExtra:
+ return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAsyncCallExtra *>(inst));
case IrInstSrcIdUnOp:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnOp *>(inst));
case IrInstSrcIdCondBr:
@@ -560,6 +564,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst));
case IrInstSrcIdWasmMemoryGrow:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst));
+ case IrInstSrcIdSrc:
+ return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSrc *>(inst));
}
zig_unreachable();
}
@@ -822,12 +828,11 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_
ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
- // TODO handle sentinel terminated arrays
expand_undef_array(g, array_val);
result = g->pass1_arena->create<ZigValue>();
result->special = array_val->special;
result->type = get_array_type(g, array_val->type->data.array.child_type,
- array_val->type->data.array.len - elem_index, nullptr);
+ array_val->type->data.array.len - elem_index, array_val->type->data.array.sentinel);
result->data.x_array.special = ConstArraySpecialNone;
result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index];
result->parent.id = ConstParentIdArray;
@@ -1170,6 +1175,10 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) {
return IrInstSrcIdCallExtra;
}
+static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsyncCallExtra *) {
+ return IrInstSrcIdAsyncCallExtra;
+}
+
static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) {
return IrInstSrcIdConst;
}
@@ -1626,6 +1635,9 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) {
return IrInstSrcIdWasmMemoryGrow;
}
+static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) {
+ return IrInstSrcIdSrc;
+}
static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
return IrInstGenIdDeclVar;
@@ -2436,6 +2448,25 @@ static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *
return &call_instruction->base;
}
+static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
+ CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc)
+{
+ IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction<IrInstSrcAsyncCallExtra>(irb, scope, source_node);
+ call_instruction->modifier = modifier;
+ call_instruction->fn_ref = fn_ref;
+ call_instruction->ret_ptr = ret_ptr;
+ call_instruction->new_stack = new_stack;
+ call_instruction->args = args;
+ call_instruction->result_loc = result_loc;
+
+ ir_ref_instruction(fn_ref, irb->current_basic_block);
+ if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block);
+ ir_ref_instruction(new_stack, irb->current_basic_block);
+ ir_ref_instruction(args, irb->current_basic_block);
+
+ return &call_instruction->base;
+}
+
static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len,
ResultLoc *result_loc)
@@ -5029,6 +5060,11 @@ static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_i
return &instruction->base;
}
+static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
+ IrInstSrcSrc *instruction = ir_build_instruction<IrInstSrcSrc>(irb, scope, source_node);
+
+ return &instruction->base;
+}
static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
@@ -6172,11 +6208,10 @@ static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *nod
static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node,
LVal lval, ResultLoc *result_loc)
{
- size_t arg_offset = 3;
- if (call_node->data.fn_call_expr.params.length < arg_offset) {
+ if (call_node->data.fn_call_expr.params.length != 4) {
add_node_error(irb->codegen, call_node,
- buf_sprintf("expected at least %" ZIG_PRI_usize " arguments, found %" ZIG_PRI_usize,
- arg_offset, call_node->data.fn_call_expr.params.length));
+ buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize,
+ call_node->data.fn_call_expr.params.length));
return irb->codegen->invalid_inst_src;
}
@@ -6195,20 +6230,37 @@ static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *aw
if (fn_ref == irb->codegen->invalid_inst_src)
return fn_ref;
- size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;
- IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count);
- for (size_t i = 0; i < arg_count; i += 1) {
- AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);
- IrInstSrc *arg = ir_gen_node(irb, arg_node, scope);
- if (arg == irb->codegen->invalid_inst_src)
- return arg;
- args[i] = arg;
- }
-
CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;
bool is_async_call_builtin = true;
- IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args,
- ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
+ AstNode *args_node = call_node->data.fn_call_expr.params.at(3);
+ if (args_node->type == NodeTypeContainerInitExpr) {
+ if (args_node->data.container_init_expr.kind == ContainerInitKindArray ||
+ args_node->data.container_init_expr.entries.length == 0)
+ {
+ size_t arg_count = args_node->data.container_init_expr.entries.length;
+ IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count);
+ for (size_t i = 0; i < arg_count; i += 1) {
+ AstNode *arg_node = args_node->data.container_init_expr.entries.at(i);
+ IrInstSrc *arg = ir_gen_node(irb, arg_node, scope);
+ if (arg == irb->codegen->invalid_inst_src)
+ return arg;
+ args[i] = arg;
+ }
+
+ IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args,
+ ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
+ return ir_lval_wrap(irb, scope, call, lval, result_loc);
+ } else {
+ exec_add_error_node(irb->codegen, irb->exec, args_node,
+ buf_sprintf("TODO: @asyncCall with anon struct literal"));
+ return irb->codegen->invalid_inst_src;
+ }
+ }
+ IrInstSrc *args = ir_gen_node(irb, args_node, scope);
+ if (args == irb->codegen->invalid_inst_src)
+ return args;
+
+ IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc);
return ir_lval_wrap(irb, scope, call, lval, result_loc);
}
@@ -7449,6 +7501,11 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
lval, result_loc);
}
+ case BuiltinFnIdSrc:
+ {
+ IrInstSrc *src_inst = ir_build_src(irb, scope, node);
+ return ir_lval_wrap(irb, scope, src_inst, lval, result_loc);
+ }
}
zig_unreachable();
}
@@ -9885,7 +9942,7 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
is_var_args = true;
break;
}
- if (param_node->data.param_decl.var_token == nullptr) {
+ if (param_node->data.param_decl.anytype_token == nullptr) {
AstNode *type_node = param_node->data.param_decl.type;
IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope);
if (type_value == irb->codegen->invalid_inst_src)
@@ -9911,7 +9968,7 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
}
IrInstSrc *return_type;
- if (node->data.fn_proto.return_var_token == nullptr) {
+ if (node->data.fn_proto.return_anytype_token == nullptr) {
if (node->data.fn_proto.return_type == nullptr) {
return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void);
} else {
@@ -10169,9 +10226,9 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
add_node_error(irb->codegen, node,
buf_sprintf("inferred array size invalid here"));
return irb->codegen->invalid_inst_src;
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
return ir_lval_wrap(irb, scope,
- ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var), lval, result_loc);
+ ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_anytype), lval, result_loc);
}
zig_unreachable();
}
@@ -10239,7 +10296,7 @@ static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *sco
case NodeTypeSuspend:
case NodeTypeEnumLiteral:
case NodeTypeInferredArrayType:
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
case NodeTypePrefixOpExpr:
add_node_error(irb->codegen, node,
buf_sprintf("invalid left-hand side to assignment"));
@@ -10461,7 +10518,7 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va
if (val == nullptr) return nullptr;
assert(const_val->type->id == ZigTypeIdPointer);
ZigType *expected_type = const_val->type->data.pointer.child_type;
- if (expected_type == codegen->builtin_types.entry_var) {
+ if (expected_type == codegen->builtin_types.entry_anytype) {
return val;
}
switch (type_has_one_possible_value(codegen, expected_type)) {
@@ -12585,28 +12642,29 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (prev_type->id == ZigTypeIdPointer &&
prev_type->data.pointer.ptr_len == PtrLenSingle &&
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
- ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown)))
+ ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown)))
{
- prev_inst = cur_inst;
+ convert_to_const_slice = false;
+ prev_inst = cur_inst;
if (prev_type->data.pointer.is_const && !cur_type->data.pointer.is_const) {
// const array pointer and non-const unknown pointer
make_the_pointer_const = true;
}
- continue;
+ continue;
}
// *[N]T to [*]T
if (cur_type->id == ZigTypeIdPointer &&
cur_type->data.pointer.ptr_len == PtrLenSingle &&
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
- ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown)))
+ ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown)))
{
if (cur_type->data.pointer.is_const && !prev_type->data.pointer.is_const) {
// const array pointer and non-const unknown pointer
make_the_pointer_const = true;
}
- continue;
+ continue;
}
// *[N]T to []T
@@ -12962,7 +13020,11 @@ static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGe
{
if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) {
IrInstGen *result = ir_const(ira, source_instr, wanted_type);
- if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type,
+ ZigValue *val = ir_resolve_const(ira, value, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, val, val->type,
result->value, wanted_type))
{
return ira->codegen->invalid_inst_gen;
@@ -14703,10 +14765,139 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou
}
static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,
- IrInstGen *value, ZigType *wanted_type)
+ IrInstGen *struct_operand, ZigType *wanted_type)
{
- ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct"));
- return ira->codegen->invalid_inst_gen;
+ Error err;
+
+ IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
+ if (type_is_invalid(struct_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
+ ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_inst_gen;
+
+ size_t actual_field_count = wanted_type->data.structure.src_field_count;
+ size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;
+
+ bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
+ || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
+ bool is_comptime = true;
+
+ // Determine if the struct_operand will be comptime.
+ // Also emit compile errors for missing fields and duplicate fields.
+ AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count);
+ ZigValue **field_values = heap::c_allocator.allocate<ZigValue *>(actual_field_count);
+ IrInstGen **casted_fields = heap::c_allocator.allocate<IrInstGen *>(actual_field_count);
+ IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
+
+ for (size_t i = 0; i < instr_field_count; i += 1) {
+ TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];
+ TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);
+ if (dst_field == nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",
+ buf_ptr(src_field->name), buf_ptr(&wanted_type->name)));
+ if (wanted_type->data.structure.decl_node) {
+ add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node,
+ buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name)));
+ }
+ add_error_note(ira->codegen, msg, src_field->decl_node,
+ buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ir_assert(src_field->decl_node != nullptr, source_instr);
+ AstNode *existing_assign_node = field_assign_nodes[dst_field->src_index];
+ if (existing_assign_node != nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("duplicate field"));
+ add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here"));
+ return ira->codegen->invalid_inst_gen;
+ }
+ field_assign_nodes[dst_field->src_index] = src_field->decl_node;
+
+ IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
+ struct_operand->value->type, false);
+ if (type_is_invalid(field_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+ IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
+ if (type_is_invalid(field_value->value->type))
+ return ira->codegen->invalid_inst_gen;
+ IrInstGen *casted_value = ir_implicit_cast(ira, field_value, dst_field->type_entry);
+ if (type_is_invalid(casted_value->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ casted_fields[dst_field->src_index] = casted_value;
+ if (need_comptime || instr_is_comptime(casted_value)) {
+ ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
+ if (field_val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+ field_val->parent.id = ConstParentIdStruct;
+ field_val->parent.data.p_struct.struct_val = const_result->value;
+ field_val->parent.data.p_struct.field_index = dst_field->src_index;
+ field_values[dst_field->src_index] = field_val;
+ } else {
+ is_comptime = false;
+ }
+ }
+
+ bool any_missing = false;
+ for (size_t i = 0; i < actual_field_count; i += 1) {
+ if (field_assign_nodes[i] != nullptr) continue;
+
+ // look for a default field value
+ TypeStructField *field = wanted_type->data.structure.fields[i];
+ memoize_field_init_val(ira->codegen, wanted_type, field);
+ if (field->init_val == nullptr) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
+ any_missing = true;
+ continue;
+ }
+ if (type_is_invalid(field->init_val->type))
+ return ira->codegen->invalid_inst_gen;
+ ZigValue *init_val_copy = ira->codegen->pass1_arena->create<ZigValue>();
+ copy_const_val(ira->codegen, init_val_copy, field->init_val);
+ init_val_copy->parent.id = ConstParentIdStruct;
+ init_val_copy->parent.data.p_struct.struct_val = const_result->value;
+ init_val_copy->parent.data.p_struct.field_index = i;
+ field_values[i] = init_val_copy;
+ casted_fields[i] = ir_const_move(ira, source_instr, init_val_copy);
+ }
+ if (any_missing)
+ return ira->codegen->invalid_inst_gen;
+
+ if (is_comptime) {
+ heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
+ IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
+ const_result->value->data.x_struct.fields = field_values;
+ return const_result;
+ }
+
+ IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
+ wanted_type, nullptr, true, true);
+ if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ for (size_t i = 0; i < actual_field_count; i += 1) {
+ TypeStructField *field = wanted_type->data.structure.fields[i];
+ IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, result_loc_inst, wanted_type, true);
+ if (type_is_invalid(field_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+ IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, field_ptr, casted_fields[i], true);
+ if (type_is_invalid(store_ptr_inst->value->type))
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
+ heap::c_allocator.deallocate(field_values, actual_field_count);
+ heap::c_allocator.deallocate(casted_fields, actual_field_count);
+
+ return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);
}
static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
@@ -14727,7 +14918,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
TypeUnionField *union_field = find_union_type_field(union_type, only_field->name);
if (union_field == nullptr) {
ir_add_error_node(ira, only_field->decl_node,
- buf_sprintf("no member named '%s' in union '%s'",
+ buf_sprintf("no field named '%s' in union '%s'",
buf_ptr(only_field->name), buf_ptr(&union_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -14849,7 +15040,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
}
// This means the wanted type is anything.
- if (wanted_type == ira->codegen->builtin_types.entry_var) {
+ if (wanted_type == ira->codegen->builtin_types.entry_anytype) {
return value;
}
@@ -15127,46 +15318,6 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
}
}
- // *[N]T to E![]T
- if (wanted_type->id == ZigTypeIdErrorUnion &&
- is_slice(wanted_type->data.error_union.payload_type) &&
- actual_type->id == ZigTypeIdPointer &&
- actual_type->data.pointer.ptr_len == PtrLenSingle &&
- actual_type->data.pointer.child_type->id == ZigTypeIdArray)
- {
- ZigType *slice_type = wanted_type->data.error_union.payload_type;
- ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
- assert(slice_ptr_type->id == ZigTypeIdPointer);
- ZigType *array_type = actual_type->data.pointer.child_type;
- bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0
- || !actual_type->data.pointer.is_const);
- if (const_ok && types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
- array_type->data.array.child_type, source_node,
- !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
- {
- // If the pointers both have ABI align, it works.
- bool ok_align = slice_ptr_type->data.pointer.explicit_alignment == 0 &&
- actual_type->data.pointer.explicit_alignment == 0;
- if (!ok_align) {
- // If either one has non ABI align, we have to resolve them both
- if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
- ResolveStatusAlignmentKnown)))
- {
- return ira->codegen->invalid_inst_gen;
- }
- if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type,
- ResolveStatusAlignmentKnown)))
- {
- return ira->codegen->invalid_inst_gen;
- }
- ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);
- }
- if (ok_align) {
- return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, nullptr);
- }
- }
- }
-
// @Vector(N,T1) to @Vector(N,T2)
if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector) {
if (actual_type->data.vector.len == wanted_type->data.vector.len &&
@@ -15346,6 +15497,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
if (is_pointery_and_elem_is_not_pointery(actual_type)) {
ZigType *dest_ptr_type = nullptr;
if (wanted_type->id == ZigTypeIdPointer &&
+ actual_type->id != ZigTypeIdOptional &&
wanted_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void)
{
dest_ptr_type = wanted_type;
@@ -15483,7 +15635,7 @@ static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *ex
static ZigType *get_ptr_elem_type(CodeGen *g, IrInstGen *ptr) {
ir_assert_gen(ptr->value->type->id == ZigTypeIdPointer, ptr);
ZigType *elem_type = ptr->value->type->data.pointer.child_type;
- if (elem_type != g->builtin_types.entry_var)
+ if (elem_type != g->builtin_types.entry_anytype)
return elem_type;
if (ir_resolve_lazy(g, ptr->base.source_node, ptr->value))
@@ -15535,7 +15687,7 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns
}
if (ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
ZigValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr->value);
- if (child_type == ira->codegen->builtin_types.entry_var) {
+ if (child_type == ira->codegen->builtin_types.entry_anytype) {
child_type = pointee->type;
}
if (pointee->special != ConstValSpecialRuntime) {
@@ -18353,7 +18505,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV
if (decl_var_instruction->var_type != nullptr) {
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->base.source_node, proposed_type);
+ explicit_type = validate_var_type(ira->codegen, &var->decl_node->data.variable_declaration, proposed_type);
if (type_is_invalid(explicit_type)) {
var->var_type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->invalid_inst_gen;
@@ -18935,7 +19087,7 @@ static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out
ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child);
if (type_is_invalid(dest_type))
return ErrorSemanticAnalyzeFail;
- *out = (dest_type != ira->codegen->builtin_types.entry_var);
+ *out = (dest_type != ira->codegen->builtin_types.entry_anytype);
return ErrorNone;
}
case ResultLocIdVar:
@@ -19141,7 +19293,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
if (type_is_invalid(dest_type))
return ira->codegen->invalid_inst_gen;
- if (dest_type == ira->codegen->builtin_types.entry_var) {
+ if (dest_type == ira->codegen->builtin_types.entry_anytype) {
return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type);
}
@@ -19287,7 +19439,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
return ira->codegen->invalid_inst_gen;
}
- if (child_type != ira->codegen->builtin_types.entry_var) {
+ if (child_type != ira->codegen->builtin_types.entry_anytype) {
if (type_size(ira->codegen, child_type) != type_size(ira->codegen, value_type)) {
// pointer cast won't work; we need a temporary location.
result_bit_cast->parent->written = parent_was_written;
@@ -19448,9 +19600,9 @@ static IrInstGen *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstSr
if (type_is_invalid(implicit_elem_type))
return ira->codegen->invalid_inst_gen;
} else {
- implicit_elem_type = ira->codegen->builtin_types.entry_var;
+ implicit_elem_type = ira->codegen->builtin_types.entry_anytype;
}
- if (implicit_elem_type == ira->codegen->builtin_types.entry_var) {
+ if (implicit_elem_type == ira->codegen->builtin_types.entry_anytype) {
Buf *bare_name = buf_alloc();
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
instruction->base.base.scope, instruction->base.base.source_node, bare_name);
@@ -19607,7 +19759,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
assert(param_decl_node->type == NodeTypeParamDecl);
IrInstGen *casted_arg;
- if (param_decl_node->data.param_decl.var_token == nullptr) {
+ if (param_decl_node->data.param_decl.anytype_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);
if (type_is_invalid(param_type))
@@ -19647,7 +19799,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
arg_part_of_generic_id = true;
casted_arg = arg;
} else {
- if (param_decl_node->data.param_decl.var_token == nullptr) {
+ if (param_decl_node->data.param_decl.anytype_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
if (type_is_invalid(param_type))
@@ -19859,7 +20011,7 @@ static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr,
}
if (ptr->value->type->data.pointer.inferred_struct_field != nullptr &&
- child_type == ira->codegen->builtin_types.entry_var)
+ child_type == ira->codegen->builtin_types.entry_anytype)
{
child_type = ptr->value->type->data.pointer.inferred_struct_field->inferred_struct_type;
}
@@ -20030,7 +20182,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
}
IrInstGen *first_arg;
- if (!first_arg_known_bare && handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type)) {
+ if (!first_arg_known_bare) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
@@ -20050,6 +20202,11 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
}
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
+ if (return_type_node == nullptr) {
+ ir_add_error(ira, &fn_ref->base,
+ buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
+ return ira->codegen->invalid_inst_gen;
+ }
ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node);
if (type_is_invalid(specified_return_type))
return ira->codegen->invalid_inst_gen;
@@ -20160,7 +20317,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
}
IrInstGen *first_arg;
- if (!first_arg_known_bare && handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type)) {
+ if (!first_arg_known_bare) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
@@ -20212,7 +20369,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
inst_fn_type_id.alignment = align_bytes;
}
- if (fn_proto_node->data.fn_proto.return_var_token == nullptr) {
+ if (fn_proto_node->data.fn_proto.return_anytype_token == nullptr) {
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node);
if (type_is_invalid(specified_return_type))
@@ -20311,7 +20468,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if (type_is_invalid(dummy_result->value->type))
return ira->codegen->invalid_inst_gen;
ZigType *res_child_type = result_loc->value->type->data.pointer.child_type;
- if (res_child_type == ira->codegen->builtin_types.entry_var) {
+ if (res_child_type == ira->codegen->builtin_types.entry_anytype) {
res_child_type = impl_fn_type_id->return_type;
}
if (!handle_is_ptr(ira->codegen, res_child_type)) {
@@ -20365,9 +20522,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
return ira->codegen->invalid_inst_gen;
IrInstGen *first_arg;
- if (param_type->id == ZigTypeIdPointer &&
- handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type))
- {
+ if (param_type->id == ZigTypeIdPointer) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
@@ -20454,7 +20609,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if (type_is_invalid(dummy_result->value->type))
return ira->codegen->invalid_inst_gen;
ZigType *res_child_type = result_loc->value->type->data.pointer.child_type;
- if (res_child_type == ira->codegen->builtin_types.entry_var) {
+ if (res_child_type == ira->codegen->builtin_types.entry_anytype) {
res_child_type = return_type;
}
if (!handle_is_ptr(ira->codegen, res_child_type)) {
@@ -20614,40 +20769,106 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr,
modifier, stack, stack_src, false, args_ptr, args_len, nullptr, result_loc);
}
-static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCallExtra *instruction) {
- IrInstGen *args = instruction->args->child;
+static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_instr, CallModifier modifier,
+ IrInstSrc *pass1_fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstGen **args_ptr, size_t args_len, ResultLoc *result_loc)
+{
+ IrInstGen *fn_ref = pass1_fn_ref->child;
+ if (type_is_invalid(fn_ref->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) {
+ ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @asyncCall"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ IrInstGen *first_arg_ptr = nullptr;
+ IrInst *first_arg_ptr_src = nullptr;
+ ZigFn *fn = nullptr;
+ if (instr_is_comptime(fn_ref)) {
+ if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
+ assert(fn_ref->value->special == ConstValSpecialStatic);
+ fn = fn_ref->value->data.x_bound_fn.fn;
+ first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
+ first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src;
+ if (type_is_invalid(first_arg_ptr->value->type))
+ return ira->codegen->invalid_inst_gen;
+ } else {
+ fn = ir_resolve_fn(ira, fn_ref);
+ }
+ }
+
+ IrInstGen *ret_ptr_uncasted = nullptr;
+ if (ret_ptr != nullptr) {
+ ret_ptr_uncasted = ret_ptr->child;
+ if (type_is_invalid(ret_ptr_uncasted->value->type))
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
+ IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack->child,
+ &new_stack->base, true, fn);
+ if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, first_arg_ptr_src,
+ modifier, casted_new_stack, &new_stack->base, true, args_ptr, args_len, ret_ptr_uncasted, result_loc);
+}
+
+static bool ir_extract_tuple_call_args(IrAnalyze *ira, IrInst *source_instr, IrInstGen *args, IrInstGen ***args_ptr, size_t *args_len) {
ZigType *args_type = args->value->type;
if (type_is_invalid(args_type))
- return ira->codegen->invalid_inst_gen;
+ return false;
if (args_type->id != ZigTypeIdStruct) {
ir_add_error(ira, &args->base,
buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
- return ira->codegen->invalid_inst_gen;
+ return false;
}
- IrInstGen **args_ptr = nullptr;
- size_t args_len = 0;
-
if (is_tuple(args_type)) {
- args_len = args_type->data.structure.src_field_count;
- args_ptr = heap::c_allocator.allocate<IrInstGen *>(args_len);
- for (size_t i = 0; i < args_len; i += 1) {
+ *args_len = args_type->data.structure.src_field_count;
+ *args_ptr = heap::c_allocator.allocate<IrInstGen *>(*args_len);
+ for (size_t i = 0; i < *args_len; i += 1) {
TypeStructField *arg_field = args_type->data.structure.fields[i];
- args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base.base, args, arg_field);
- if (type_is_invalid(args_ptr[i]->value->type))
- return ira->codegen->invalid_inst_gen;
+ (*args_ptr)[i] = ir_analyze_struct_value_field_value(ira, source_instr, args, arg_field);
+ if (type_is_invalid((*args_ptr)[i]->value->type))
+ return false;
}
} else {
ir_add_error(ira, &args->base, buf_sprintf("TODO: struct args"));
+ return false;
+ }
+ return true;
+}
+
+static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCallExtra *instruction) {
+ IrInstGen *args = instruction->args->child;
+ IrInstGen **args_ptr = nullptr;
+ size_t args_len = 0;
+ if (!ir_extract_tuple_call_args(ira, &instruction->base.base, args, &args_ptr, &args_len)) {
return ira->codegen->invalid_inst_gen;
}
+
IrInstGen *result = ir_analyze_call_extra(ira, &instruction->base.base, instruction->options,
instruction->fn_ref, args_ptr, args_len, instruction->result_loc);
heap::c_allocator.deallocate(args_ptr, args_len);
return result;
}
+static IrInstGen *ir_analyze_instruction_async_call_extra(IrAnalyze *ira, IrInstSrcAsyncCallExtra *instruction) {
+ IrInstGen *args = instruction->args->child;
+ IrInstGen **args_ptr = nullptr;
+ size_t args_len = 0;
+ if (!ir_extract_tuple_call_args(ira, &instruction->base.base, args, &args_ptr, &args_len)) {
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ IrInstGen *result = ir_analyze_async_call_extra(ira, &instruction->base.base, instruction->modifier,
+ instruction->fn_ref, instruction->ret_ptr, instruction->new_stack, args_ptr, args_len, instruction->result_loc);
+ heap::c_allocator.deallocate(args_ptr, args_len);
+ return result;
+}
+
static IrInstGen *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstSrcCallArgs *instruction) {
IrInstGen **args_ptr = heap::c_allocator.allocate<IrInstGen *>(instruction->args_len);
for (size_t i = 0; i < instruction->args_len; i += 1) {
@@ -20881,17 +21102,24 @@ static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction
if (type_is_invalid(expr_type))
return ira->codegen->invalid_inst_gen;
- if (!(expr_type->id == ZigTypeIdInt || expr_type->id == ZigTypeIdComptimeInt ||
- expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat ||
- expr_type->id == ZigTypeIdVector))
- {
- ir_add_error(ira, &instruction->base.base,
- buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name)));
- return ira->codegen->invalid_inst_gen;
- }
-
bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
+ switch (expr_type->id) {
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdFloat:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdVector:
+ break;
+ case ZigTypeIdInt:
+ if (is_wrap_op || expr_type->data.integral.is_signed)
+ break;
+ ZIG_FALLTHROUGH;
+ default:
+ ir_add_error(ira, &instruction->base.base,
+ buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name)));
+ return ira->codegen->invalid_inst_gen;
+ }
+
ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
if (instr_is_comptime(value)) {
@@ -22112,7 +22340,7 @@ static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
inferred_struct_field->inferred_struct_type = container_type;
inferred_struct_field->field_name = field_name;
- ZigType *elem_type = ira->codegen->builtin_types.entry_var;
+ ZigType *elem_type = ira->codegen->builtin_types.entry_anytype;
ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,
PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
@@ -22407,7 +22635,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel
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_sprintf("no field named '%s' in '%s'", buf_ptr(field_name),
buf_ptr(&container_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -23834,7 +24062,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi
TypeUnionField *type_field = find_union_type_field(union_type, field_name);
if (type_field == nullptr) {
ir_add_error_node(ira, field_source_node,
- buf_sprintf("no member named '%s' in union '%s'",
+ buf_sprintf("no field named '%s' in union '%s'",
buf_ptr(field_name), buf_ptr(&union_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -23930,7 +24158,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc
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_sprintf("no field named '%s' in struct '%s'",
buf_ptr(field->name), buf_ptr(&container_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -23965,7 +24193,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc
memoize_field_init_val(ira->codegen, container_type, field);
if (field->init_val == nullptr) {
ir_add_error(ira, source_instr,
- buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name)));
+ buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
any_missing = true;
continue;
}
@@ -24890,7 +25118,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_ent
fields[5]->special = ConstValSpecialStatic;
fields[5]->type = ira->codegen->builtin_types.entry_bool;
fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
- // sentinel: var
+ // sentinel: anytype
ensure_field_index(result->type, "sentinel", 6);
fields[6]->special = ConstValSpecialStatic;
if (attrs_type->data.pointer.child_type->id != ZigTypeIdOpaque) {
@@ -25018,7 +25246,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
fields[1]->special = ConstValSpecialStatic;
fields[1]->type = ira->codegen->builtin_types.entry_type;
fields[1]->data.x_type = type_entry->data.array.child_type;
- // sentinel: var
+ // sentinel: anytype
fields[2]->special = ConstValSpecialStatic;
fields[2]->type = get_optional_type(ira->codegen, type_entry->data.array.child_type);
fields[2]->data.x_optional = type_entry->data.array.sentinel;
@@ -25318,7 +25546,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
result->special = ConstValSpecialStatic;
result->type = ir_type_info_get_type(ira, "Struct", nullptr);
- ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 3);
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
result->data.x_struct.fields = fields;
// layout: ContainerLayout
@@ -25373,7 +25601,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
inner_fields[2]->data.x_type = struct_field->type_entry;
- // default_value: var
+ // default_value: anytype
inner_fields[3]->special = ConstValSpecialStatic;
inner_fields[3]->type = get_optional_type2(ira->codegen, struct_field->type_entry);
if (inner_fields[3]->type == nullptr) return ErrorSemanticAnalyzeFail;
@@ -25399,6 +25627,12 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
return err;
}
+ // is_tuple: bool
+ ensure_field_index(result->type, "is_tuple", 3);
+ fields[3]->special = ConstValSpecialStatic;
+ fields[3]->type = ira->codegen->builtin_types.entry_bool;
+ fields[3]->data.x_bool = is_tuple(type_entry);
+
break;
}
case ZigTypeIdFn:
@@ -25504,9 +25738,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
break;
}
case ZigTypeIdFnFrame:
- ir_add_error(ira, source_instr,
- buf_sprintf("compiler bug: TODO @typeInfo for async function frames. https://github.com/ziglang/zig/issues/3066"));
- return ErrorSemanticAnalyzeFail;
+ {
+ result = ira->codegen->pass1_arena->create<ZigValue>();
+ result->special = ConstValSpecialStatic;
+ result->type = ir_type_info_get_type(ira, "Frame", nullptr);
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+ result->data.x_struct.fields = fields;
+ ZigFn *fn = type_entry->data.frame.fn;
+ // function: anytype
+ ensure_field_index(result->type, "function", 0);
+ fields[0] = create_const_fn(ira->codegen, fn);
+ break;
+ }
}
assert(result != nullptr);
@@ -25676,6 +25919,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
{
return ira->codegen->invalid_inst_gen->value->type;
}
+ if (sentinel != nullptr && (size_enum_index == BuiltinPtrSizeOne || size_enum_index == BuiltinPtrSizeC)) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
if (bi == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
@@ -25709,7 +25957,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
0, // host_int_bytes
is_allowzero,
VECTOR_INDEX_NONE, nullptr, sentinel);
- if (size_enum_index != 2)
+ if (size_enum_index != BuiltinPtrSizeSlice)
return ptr_type;
return get_slice_type(ira->codegen, ptr_type);
}
@@ -25775,10 +26023,90 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
ZigType *child_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "child", 0);
return get_any_frame_type(ira->codegen, child_type);
}
- case ZigTypeIdErrorSet:
- case ZigTypeIdEnum:
- case ZigTypeIdFnFrame:
case ZigTypeIdEnumLiteral:
+ return ira->codegen->builtin_types.entry_enum_literal;
+ case ZigTypeIdFnFrame: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == ir_type_info_get_type(ira, "Frame", nullptr));
+ ZigValue *function = get_const_field(ira, source_instr->source_node, payload, "function", 0);
+ assert(function->type->id == ZigTypeIdFn);
+ ZigFn *fn = function->data.x_ptr.data.fn.fn_entry;
+ return get_fn_frame_type(ira->codegen, fn);
+ }
+ case ZigTypeIdErrorSet: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type->id == ZigTypeIdOptional);
+ ZigValue *slice = payload->data.x_optional;
+ if (slice == nullptr)
+ return ira->codegen->builtin_types.entry_global_error_set;
+ assert(slice->special == ConstValSpecialStatic);
+ assert(is_slice(slice->type));
+ ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
+ Buf bare_name = BUF_INIT;
+ buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->old_irb.exec, "error", source_instr->scope, source_instr->source_node, &bare_name));
+ err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
+ err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
+ err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
+ ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index];
+ assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);;
+ assert(ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val;
+ assert(arr->special == ConstValSpecialStatic);
+ assert(arr->data.x_array.special == ConstArraySpecialNone);
+ ZigValue *len = slice->data.x_struct.fields[slice_len_index];
+ size_t count = bigint_as_usize(&len->data.x_bigint);
+ err_set_type->data.error_set.err_count = count;
+ err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(count);
+ bool *already_set = heap::c_allocator.allocate<bool>(ira->codegen->errors_by_index.length + count);
+ for (size_t i = 0; i < count; i++) {
+ ZigValue *error = &arr->data.x_array.data.s_none.elements[i];
+ assert(error->type == ir_type_info_get_type(ira, "Error", nullptr));
+ ErrorTableEntry *err_entry = heap::c_allocator.create<ErrorTableEntry>();
+ err_entry->decl_node = source_instr->source_node;
+ ZigValue *name_slice = get_const_field(ira, source_instr->source_node, error, "name", 0);
+ ZigValue *name_ptr = name_slice->data.x_struct.fields[slice_ptr_index];
+ ZigValue *name_len = name_slice->data.x_struct.fields[slice_len_index];
+ assert(name_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ assert(name_ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *name_arr = name_ptr->data.x_ptr.data.base_array.array_val;
+ assert(name_arr->special == ConstValSpecialStatic);
+ switch (name_arr->data.x_array.special) {
+ case ConstArraySpecialUndef:
+ return ira->codegen->invalid_inst_gen->value->type;
+ case ConstArraySpecialNone: {
+ buf_resize(&err_entry->name, 0);
+ size_t name_count = bigint_as_usize(&name_len->data.x_bigint);
+ for (size_t j = 0; j < name_count; j++) {
+ ZigValue *ch_val = &name_arr->data.x_array.data.s_none.elements[j];
+ unsigned ch = bigint_as_u32(&ch_val->data.x_bigint);
+ buf_append_char(&err_entry->name, ch);
+ }
+ break;
+ }
+ case ConstArraySpecialBuf:
+ buf_init_from_buf(&err_entry->name, name_arr->data.x_array.data.s_buf);
+ break;
+ }
+ auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry);
+ if (existing_entry) {
+ err_entry->value = existing_entry->value->value;
+ } else {
+ size_t error_value_count = ira->codegen->errors_by_index.length;
+ assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count));
+ err_entry->value = error_value_count;
+ ira->codegen->errors_by_index.append(err_entry);
+ }
+ if (already_set[err_entry->value]) {
+ ir_add_error(ira, source_instr, buf_sprintf("duplicate error: %s", buf_ptr(&err_entry->name)));
+ return ira->codegen->invalid_inst_gen->value->type;
+ } else {
+ already_set[err_entry->value] = true;
+ }
+ err_set_type->data.error_set.errors[i] = err_entry;
+ }
+ return err_set_type;
+ }
+ case ZigTypeIdEnum:
ir_add_error(ira, source_instr, buf_sprintf(
"TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
return ira->codegen->invalid_inst_gen->value->type;
@@ -26370,6 +26698,10 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa
}
if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeInt) {
+ ZigValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
}
@@ -26407,16 +26739,20 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo
}
}
- if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
- return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
- }
-
if (target->value->type->id != ZigTypeIdFloat) {
ir_add_error(ira, &instruction->target->base, buf_sprintf("expected float type, found '%s'",
buf_ptr(&target->value->type->name)));
return ira->codegen->invalid_inst_gen;
}
+ if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeFloat) {
+ ZigValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_inst_gen;
+
+ return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type);
+ }
+
return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type);
}
@@ -28660,7 +28996,37 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
ir_add_error(ira, &instruction->base.base,
buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
return ira->codegen->invalid_inst_gen;
- }
+ } else if(switch_type->id == ZigTypeIdMetaType) {
+ HashMap<const ZigType*, IrInstGen*, type_ptr_hash, type_ptr_eql> prevs;
+ // HashMap doubles capacity when reaching 60% capacity,
+ // because we know the size at init we can avoid reallocation by doubling it here
+ prevs.init(instruction->range_count * 2);
+ for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
+ IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i];
+
+ IrInstGen *value = range->start->child;
+ IrInstGen *casted_value = ir_implicit_cast(ira, value, switch_type);
+ if (type_is_invalid(casted_value->value->type)) {
+ prevs.deinit();
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
+ if (!const_expr_val) {
+ prevs.deinit();
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ auto entry = prevs.put_unique(const_expr_val->data.x_type, value);
+ if(entry != nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, &value->base, buf_sprintf("duplicate switch value"));
+ add_error_note(ira->codegen, msg, entry->value->base.source_node, buf_sprintf("previous value is here"));
+ prevs.deinit();
+ return ira->codegen->invalid_inst_gen;
+ }
+ }
+ prevs.deinit();
+ }
return ir_const_void(ira, &instruction->base.base);
}
@@ -29650,7 +30016,7 @@ static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgTy
if (arg_index >= fn_type_id->param_count) {
if (instruction->allow_var) {
// TODO remove this with var args
- return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_var);
+ return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_anytype);
}
ir_add_error(ira, &arg_index_inst->base,
buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments",
@@ -29664,7 +30030,7 @@ static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgTy
ir_assert(fn_type->data.fn.is_generic, &instruction->base.base);
if (instruction->allow_var) {
- return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_var);
+ return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_anytype);
} else {
ir_add_error(ira, &arg_index_inst->base,
buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic",
@@ -30173,6 +30539,21 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdSqrt:
f128M_sqrt(in, out);
break;
+ case BuiltinFnIdFabs:
+ f128M_abs(in, out);
+ break;
+ case BuiltinFnIdFloor:
+ f128M_roundToInt(in, softfloat_round_min, false, out);
+ break;
+ case BuiltinFnIdCeil:
+ f128M_roundToInt(in, softfloat_round_max, false, out);
+ break;
+ case BuiltinFnIdTrunc:
+ f128M_trunc(in, out);
+ break;
+ case BuiltinFnIdRound:
+ f128M_roundToInt(in, softfloat_round_near_maxMag, false, out);
+ break;
case BuiltinFnIdNearbyInt:
case BuiltinFnIdSin:
case BuiltinFnIdCos:
@@ -30181,11 +30562,6 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdLog:
case BuiltinFnIdLog10:
case BuiltinFnIdLog2:
- case BuiltinFnIdFabs:
- case BuiltinFnIdFloor:
- case BuiltinFnIdCeil:
- case BuiltinFnIdTrunc:
- case BuiltinFnIdRound:
return ir_add_error(ira, source_instr,
buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
float_op_to_name(fop), buf_ptr(&float_type->name)));
@@ -30769,6 +31145,64 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil
return ir_build_spill_end_gen(ira, &instruction->base.base, begin, operand->value->type);
}
+static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instruction) {
+ ZigFn *fn_entry = scope_fn_entry(instruction->base.base.scope);
+ if (fn_entry == nullptr) {
+ ir_add_error(ira, &instruction->base.base, buf_sprintf("@src outside function"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigType *u8_ptr = get_pointer_to_type_extra2(
+ ira->codegen, ira->codegen->builtin_types.entry_u8,
+ true, false, PtrLenUnknown,
+ 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, ira->codegen->intern.for_zero_byte());
+ ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
+
+ ZigType *source_location_type = get_builtin_type(ira->codegen, "SourceLocation");
+ if (type_resolve(ira->codegen, source_location_type, ResolveStatusSizeKnown)) {
+ zig_unreachable();
+ }
+
+ ZigValue *result = ira->codegen->pass1_arena->create<ZigValue>();
+ result->special = ConstValSpecialStatic;
+ result->type = source_location_type;
+
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
+ result->data.x_struct.fields = fields;
+
+ // file: [:0]const u8
+ ensure_field_index(source_location_type, "file", 0);
+ fields[0]->special = ConstValSpecialStatic;
+
+ ZigType *import = instruction->base.base.source_node->owner;
+ Buf *path = import->data.structure.root_struct->path;
+ ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee;
+ init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true);
+ fields[0]->type = u8_slice;
+
+ // fn_name: [:0]const u8
+ ensure_field_index(source_location_type, "fn_name", 1);
+ fields[1]->special = ConstValSpecialStatic;
+
+ ZigValue *fn_name = create_const_str_lit(ira->codegen, &fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
+ init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true);
+ fields[1]->type = u8_slice;
+
+ // line: u32
+ ensure_field_index(source_location_type, "line", 2);
+ fields[2]->special = ConstValSpecialStatic;
+ fields[2]->type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[2]->data.x_bigint, instruction->base.base.source_node->line + 1);
+
+ // column: u32
+ ensure_field_index(source_location_type, "column", 3);
+ fields[3]->special = ConstValSpecialStatic;
+ fields[3]->type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[3]->data.x_bigint, instruction->base.base.source_node->column + 1);
+
+ return ir_const_move(ira, &instruction->base.base, result);
+}
+
static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruction) {
switch (instruction->id) {
case IrInstSrcIdInvalid:
@@ -30802,6 +31236,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_call_args(ira, (IrInstSrcCallArgs *)instruction);
case IrInstSrcIdCallExtra:
return ir_analyze_instruction_call_extra(ira, (IrInstSrcCallExtra *)instruction);
+ case IrInstSrcIdAsyncCallExtra:
+ return ir_analyze_instruction_async_call_extra(ira, (IrInstSrcAsyncCallExtra *)instruction);
case IrInstSrcIdBr:
return ir_analyze_instruction_br(ira, (IrInstSrcBr *)instruction);
case IrInstSrcIdCondBr:
@@ -31040,6 +31476,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
case IrInstSrcIdWasmMemoryGrow:
return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction);
+ case IrInstSrcIdSrc:
+ return ir_analyze_instruction_src(ira, (IrInstSrcSrc *)instruction);
}
zig_unreachable();
}
@@ -31309,6 +31747,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdDeclVar:
case IrInstSrcIdStorePtr:
case IrInstSrcIdCallExtra:
+ case IrInstSrcIdAsyncCallExtra:
case IrInstSrcIdCall:
case IrInstSrcIdCallArgs:
case IrInstSrcIdReturn:
@@ -31435,6 +31874,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdAlloca:
case IrInstSrcIdSpillEnd:
case IrInstSrcIdWasmMemorySize:
+ case IrInstSrcIdSrc:
return false;
case IrInstSrcIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index c826d76e03..0acde512f6 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -5,6 +5,7 @@
* See http://opensource.org/licenses/MIT
*/
+#include "all_types.hpp"
#include "analyze.hpp"
#include "ir.hpp"
#include "ir_print.hpp"
@@ -55,6 +56,36 @@ struct IrPrintGen {
static void ir_print_other_inst_src(IrPrintSrc *irp, IrInstSrc *inst);
static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst);
+static void ir_print_call_modifier(FILE *f, CallModifier modifier) {
+ switch (modifier) {
+ case CallModifierNone:
+ break;
+ case CallModifierNoSuspend:
+ fprintf(f, "nosuspend ");
+ break;
+ case CallModifierAsync:
+ fprintf(f, "async ");
+ break;
+ case CallModifierNeverTail:
+ fprintf(f, "notail ");
+ break;
+ case CallModifierNeverInline:
+ fprintf(f, "noinline ");
+ break;
+ case CallModifierAlwaysTail:
+ fprintf(f, "tail ");
+ break;
+ case CallModifierAlwaysInline:
+ fprintf(f, "inline ");
+ break;
+ case CallModifierCompileTime:
+ fprintf(f, "comptime ");
+ break;
+ case CallModifierBuiltin:
+ zig_unreachable();
+ }
+}
+
const char* ir_inst_src_type_str(IrInstSrcId id) {
switch (id) {
case IrInstSrcIdInvalid:
@@ -97,6 +128,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcVarPtr";
case IrInstSrcIdCallExtra:
return "SrcCallExtra";
+ case IrInstSrcIdAsyncCallExtra:
+ return "SrcAsyncCallExtra";
case IrInstSrcIdCall:
return "SrcCall";
case IrInstSrcIdCallArgs:
@@ -325,6 +358,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcWasmMemorySize";
case IrInstSrcIdWasmMemoryGrow:
return "SrcWasmMemoryGrow";
+ case IrInstSrcIdSrc:
+ return "SrcSrc";
}
zig_unreachable();
}
@@ -849,6 +884,23 @@ static void ir_print_call_extra(IrPrintSrc *irp, IrInstSrcCallExtra *instruction
ir_print_result_loc(irp, instruction->result_loc);
}
+static void ir_print_async_call_extra(IrPrintSrc *irp, IrInstSrcAsyncCallExtra *instruction) {
+ fprintf(irp->f, "modifier=");
+ ir_print_call_modifier(irp->f, instruction->modifier);
+ fprintf(irp->f, ", fn=");
+ ir_print_other_inst_src(irp, instruction->fn_ref);
+ if (instruction->ret_ptr != nullptr) {
+ fprintf(irp->f, ", ret_ptr=");
+ ir_print_other_inst_src(irp, instruction->ret_ptr);
+ }
+ fprintf(irp->f, ", new_stack=");
+ ir_print_other_inst_src(irp, instruction->new_stack);
+ fprintf(irp->f, ", args=");
+ ir_print_other_inst_src(irp, instruction->args);
+ fprintf(irp->f, ", result=");
+ ir_print_result_loc(irp, instruction->result_loc);
+}
+
static void ir_print_call_args(IrPrintSrc *irp, IrInstSrcCallArgs *instruction) {
fprintf(irp->f, "opts=");
ir_print_other_inst_src(irp, instruction->options);
@@ -866,33 +918,7 @@ static void ir_print_call_args(IrPrintSrc *irp, IrInstSrcCallArgs *instruction)
}
static void ir_print_call_src(IrPrintSrc *irp, IrInstSrcCall *call_instruction) {
- switch (call_instruction->modifier) {
- case CallModifierNone:
- break;
- case CallModifierNoSuspend:
- fprintf(irp->f, "nosuspend ");
- break;
- case CallModifierAsync:
- fprintf(irp->f, "async ");
- break;
- case CallModifierNeverTail:
- fprintf(irp->f, "notail ");
- break;
- case CallModifierNeverInline:
- fprintf(irp->f, "noinline ");
- break;
- case CallModifierAlwaysTail:
- fprintf(irp->f, "tail ");
- break;
- case CallModifierAlwaysInline:
- fprintf(irp->f, "inline ");
- break;
- case CallModifierCompileTime:
- fprintf(irp->f, "comptime ");
- break;
- case CallModifierBuiltin:
- zig_unreachable();
- }
+ ir_print_call_modifier(irp->f, call_instruction->modifier);
if (call_instruction->fn_entry) {
fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
} else {
@@ -911,33 +937,7 @@ static void ir_print_call_src(IrPrintSrc *irp, IrInstSrcCall *call_instruction)
}
static void ir_print_call_gen(IrPrintGen *irp, IrInstGenCall *call_instruction) {
- switch (call_instruction->modifier) {
- case CallModifierNone:
- break;
- case CallModifierNoSuspend:
- fprintf(irp->f, "nosuspend ");
- break;
- case CallModifierAsync:
- fprintf(irp->f, "async ");
- break;
- case CallModifierNeverTail:
- fprintf(irp->f, "notail ");
- break;
- case CallModifierNeverInline:
- fprintf(irp->f, "noinline ");
- break;
- case CallModifierAlwaysTail:
- fprintf(irp->f, "tail ");
- break;
- case CallModifierAlwaysInline:
- fprintf(irp->f, "inline ");
- break;
- case CallModifierCompileTime:
- fprintf(irp->f, "comptime ");
- break;
- case CallModifierBuiltin:
- zig_unreachable();
- }
+ ir_print_call_modifier(irp->f, call_instruction->modifier);
if (call_instruction->fn_entry) {
fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
} else {
@@ -1744,6 +1744,10 @@ static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *
fprintf(irp->f, ")");
}
+static void ir_print_builtin_src(IrPrintSrc *irp, IrInstSrcSrc *instruction) {
+ fprintf(irp->f, "@src()");
+}
+
static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
fprintf(irp->f, "@memset(");
ir_print_other_inst_src(irp, instruction->dest_ptr);
@@ -2613,6 +2617,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdCallExtra:
ir_print_call_extra(irp, (IrInstSrcCallExtra *)instruction);
break;
+ case IrInstSrcIdAsyncCallExtra:
+ ir_print_async_call_extra(irp, (IrInstSrcAsyncCallExtra *)instruction);
+ break;
case IrInstSrcIdCall:
ir_print_call_src(irp, (IrInstSrcCall *)instruction);
break;
@@ -2994,6 +3001,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdWasmMemoryGrow:
ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction);
break;
+ case IrInstSrcIdSrc:
+ ir_print_builtin_src(irp, (IrInstSrcSrc *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/src/list.hpp b/src/list.hpp
index 2c6d90c855..803a251437 100644
--- a/src/list.hpp
+++ b/src/list.hpp
@@ -19,6 +19,9 @@ struct ZigList {
ensure_capacity(length + 1);
items[length++] = item;
}
+ void append_assuming_capacity(const T& item) {
+ items[length++] = item;
+ }
// remember that the pointer to this item is invalid after you
// modify the length of the list
const T & at(size_t index) const {
diff --git a/src/os.cpp b/src/os.cpp
index 26ed0dc4e1..33d98fd416 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -6,8 +6,13 @@
*/
#include "os.hpp"
+#include "buffer.hpp"
+#include "heap.hpp"
#include "util.hpp"
#include "error.hpp"
+#include "util_base.hpp"
+#include <stdint.h>
+#include <stdio.h>
#if defined(_WIN32)
@@ -73,6 +78,8 @@ typedef SSIZE_T ssize_t;
#endif
#if defined(ZIG_OS_WINDOWS)
+static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le);
+static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8);
static uint64_t windows_perf_freq;
#elif defined(__MACH__)
static clock_serv_t macos_calendar_clock;
@@ -148,15 +155,21 @@ static void os_spawn_process_windows(ZigList<const char *> &args, Termination *t
os_windows_create_command_line(&command_line, args);
PROCESS_INFORMATION piProcInfo = {0};
- STARTUPINFO siStartInfo = {0};
- siStartInfo.cb = sizeof(STARTUPINFO);
+ STARTUPINFOW siStartInfo = {0};
+ siStartInfo.cb = sizeof(STARTUPINFOW);
- const char *exe = args.at(0);
- BOOL success = CreateProcessA(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
+ Slice<uint8_t> exe_slice = str(args.at(0));
+ auto exe_utf16_slice = Slice<WCHAR>::alloc(exe_slice.len + 1);
+ exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0;
+
+ auto command_line_utf16 = Slice<WCHAR>::alloc(buf_len(&command_line) + 1);
+ command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0;
+
+ BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr,
&siStartInfo, &piProcInfo);
if (!success) {
- zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line));
+ zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line));
}
WaitForSingleObject(piProcInfo.hProcess, INFINITE);
@@ -269,11 +282,13 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
Error os_path_real(Buf *rel_path, Buf *out_abs_path) {
#if defined(ZIG_OS_WINDOWS)
- buf_resize(out_abs_path, 4096);
- if (_fullpath(buf_ptr(out_abs_path), buf_ptr(rel_path), buf_len(out_abs_path)) == nullptr) {
- zig_panic("_fullpath failed");
+ PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path));
+ PathSpace out_abs_path_space;
+
+ if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) {
+ zig_panic("_wfullpath failed");
}
- buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));
+ utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]);
return ErrorNone;
#elif defined(ZIG_OS_POSIX)
buf_resize(out_abs_path, PATH_MAX + 1);
@@ -773,7 +788,8 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {
Error os_file_exists(Buf *full_path, bool *result) {
#if defined(ZIG_OS_WINDOWS)
- *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
+ *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES;
return ErrorNone;
#else
*result = access(buf_ptr(full_path), F_OK) != -1;
@@ -1021,7 +1037,12 @@ Error os_exec_process(ZigList<const char *> &args,
}
Error os_write_file(Buf *full_path, Buf *contents) {
+#if defined(ZIG_OS_WINDOWS)
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
+ FILE *f = _wfopen(&path_space.data.items[0], L"wb");
+#else
FILE *f = fopen(buf_ptr(full_path), "wb");
+#endif
if (!f) {
zig_panic("os_write_file failed for %s", buf_ptr(full_path));
}
@@ -1056,7 +1077,12 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
Error os_dump_file(Buf *src_path, FILE *dest_file) {
Error err;
+#if defined(ZIG_OS_WINDOWS)
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
+ FILE *src_f = _wfopen(&path_space.data.items[0], L"rb");
+#else
FILE *src_f = fopen(buf_ptr(src_path), "rb");
+#endif
if (!src_f) {
int err = errno;
if (err == ENOENT) {
@@ -1173,7 +1199,12 @@ Error os_update_file(Buf *src_path, Buf *dst_path) {
}
Error os_copy_file(Buf *src_path, Buf *dest_path) {
+#if defined(ZIG_OS_WINDOWS)
+ PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
+ FILE *src_f = _wfopen(&src_path_space.data.items[0], L"rb");
+#else
FILE *src_f = fopen(buf_ptr(src_path), "rb");
+#endif
if (!src_f) {
int err = errno;
if (err == ENOENT) {
@@ -1184,7 +1215,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
return ErrorFileSystem;
}
}
+#if defined(ZIG_OS_WINDOWS)
+ PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
+ FILE *dest_f = _wfopen(&dest_path_space.data.items[0], L"wb");
+#else
FILE *dest_f = fopen(buf_ptr(dest_path), "wb");
+#endif
if (!dest_f) {
int err = errno;
if (err == ENOENT) {
@@ -1205,7 +1241,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
}
Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
+#if defined(ZIG_OS_WINDOWS)
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
+ FILE *f = _wfopen(&path_space.data.items[0], L"rb");
+#else
FILE *f = fopen(buf_ptr(full_path), "rb");
+#endif
if (!f) {
switch (errno) {
case EACCES:
@@ -1230,11 +1271,11 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
Error os_get_cwd(Buf *out_cwd) {
#if defined(ZIG_OS_WINDOWS)
- char buf[4096];
- if (GetCurrentDirectory(4096, buf) == 0) {
+ PathSpace path_space;
+ if (GetCurrentDirectoryW(PATH_MAX_WIDE, &path_space.data.items[0]) == 0) {
zig_panic("GetCurrentDirectory failed");
}
- buf_init_from_str(out_cwd, buf);
+ utf16le_ptr_to_utf8(out_cwd, &path_space.data.items[0]);
return ErrorNone;
#elif defined(ZIG_OS_POSIX)
char buf[PATH_MAX];
@@ -1330,7 +1371,9 @@ Error os_rename(Buf *src_path, Buf *dest_path) {
return ErrorNone;
}
#if defined(ZIG_OS_WINDOWS)
- if (!MoveFileExA(buf_ptr(src_path), buf_ptr(dest_path), MOVEFILE_REPLACE_EXISTING)) {
+ PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
+ PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
+ if (!MoveFileExW(&src_path_space.data.items[0], &dest_path_space.data.items[0], MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
return ErrorFileSystem;
}
#else
@@ -1426,7 +1469,15 @@ Error os_make_path(Buf *path) {
Error os_make_dir(Buf *path) {
#if defined(ZIG_OS_WINDOWS)
- if (!CreateDirectory(buf_ptr(path), NULL)) {
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(path));
+ if (memEql(buf_to_slice(path), str("C:\\dev\\tést"))) {
+ for (size_t i = 0; i < path_space.len; i++) {
+ fprintf(stderr, "%d ", path_space.data.items[i]);
+ }
+ fprintf(stderr, "\n");
+ }
+
+ if (!CreateDirectoryW(&path_space.data.items[0], NULL)) {
if (GetLastError() == ERROR_ALREADY_EXISTS)
return ErrorPathAlreadyExists;
if (GetLastError() == ERROR_PATH_NOT_FOUND)
@@ -1531,18 +1582,13 @@ int os_init(void) {
Error os_self_exe_path(Buf *out_path) {
#if defined(ZIG_OS_WINDOWS)
- buf_resize(out_path, 256);
- for (;;) {
- DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path));
- if (copied_amt <= 0) {
- return ErrorFileNotFound;
- }
- if (copied_amt < buf_len(out_path)) {
- buf_resize(out_path, copied_amt);
- return ErrorNone;
- }
- buf_resize(out_path, buf_len(out_path) * 2);
+ PathSpace path_space;
+ DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE);
+ if (copied_amt <= 0) {
+ return ErrorFileNotFound;
}
+ utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]);
+ return ErrorNone;
#elif defined(ZIG_OS_DARWIN)
// How long is the executable's path?
@@ -1719,6 +1765,15 @@ static uint8_t utf8CodepointSequenceLength(uint32_t c) {
zig_unreachable();
}
+// Ported from std.unicode.utf8ByteSequenceLength
+static uint8_t utf8ByteSequenceLength(uint8_t first_byte) {
+ if (first_byte < 0b10000000) return 1;
+ if ((first_byte & 0b11100000) == 0b11000000) return 2;
+ if ((first_byte & 0b11110000) == 0b11100000) return 3;
+ if ((first_byte & 0b11111000) == 0b11110000) return 4;
+ zig_unreachable();
+}
+
// Ported from std/unicode.zig
static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
size_t length = utf8CodepointSequenceLength(c);
@@ -1753,6 +1808,80 @@ static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
return length;
}
+// Ported from std.unicode.utf8Decode2
+static uint32_t utf8Decode2(Slice<uint8_t> bytes) {
+ assert(bytes.len == 2);
+ assert((bytes.at(0) & 0b11100000) == 0b11000000);
+
+ uint32_t value = bytes.at(0) & 0b00011111;
+ assert((bytes.at(1) & 0b11000000) == 0b10000000);
+ value <<= 6;
+ value |= bytes.at(1) & 0b00111111;
+
+ assert(value >= 0x80);
+ return value;
+}
+
+// Ported from std.unicode.utf8Decode3
+static uint32_t utf8Decode3(Slice<uint8_t> bytes) {
+ assert(bytes.len == 3);
+ assert((bytes.at(0) & 0b11110000) == 0b11100000);
+
+ uint32_t value = bytes.at(0) & 0b00001111;
+ assert((bytes.at(1) & 0b11000000) == 0b10000000);
+ value <<= 6;
+ value |= bytes.at(1) & 0b00111111;
+
+ assert((bytes.at(2) & 0b11000000) == 0b10000000);
+ value <<= 6;
+ value |= bytes.at(2) & 0b00111111;
+
+ assert(value >= 0x80);
+ assert(value < 0xd800 || value > 0xdfff);
+ return value;
+}
+
+// Ported from std.unicode.utf8Decode4
+static uint32_t utf8Decode4(Slice<uint8_t> bytes) {
+ assert(bytes.len == 4);
+ assert((bytes.at(0) & 0b11111000) == 0b11110000);
+
+ uint32_t value = bytes.at(0) & 0b00000111;
+ assert((bytes.at(1) & 0b11000000) == 0b10000000);
+ value <<= 6;
+ value |= bytes.at(1) & 0b00111111;
+
+ assert((bytes.at(2) & 0b11000000) == 0b10000000);
+ value <<= 6;
+ value |= bytes.at(2) & 0b00111111;
+
+ assert((bytes.at(3) & 0b11000000) == 0b10000000);
+ value <<= 6;
+ value |= bytes.at(3) & 0b00111111;
+
+ assert(value >= 0x10000 && value <= 0x10FFFF);
+ return value;
+}
+
+// Ported from std.unicode.utf8Decode
+static uint32_t utf8Decode(Slice<uint8_t> bytes) {
+ switch (bytes.len) {
+ case 1:
+ return bytes.at(0);
+ break;
+ case 2:
+ return utf8Decode2(bytes);
+ break;
+ case 3:
+ return utf8Decode3(bytes);
+ break;
+ case 4:
+ return utf8Decode4(bytes);
+ break;
+ default:
+ zig_unreachable();
+ }
+}
// Ported from std.unicode.utf16leToUtf8Alloc
static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
// optimistically guess that it will all be ascii.
@@ -1770,6 +1899,60 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
out_index += utf8_len;
}
}
+
+// Ported from std.unicode.utf8ToUtf16Le
+static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8) {
+ size_t dest_i = 0;
+ size_t src_i = 0;
+ while (src_i < utf8.len) {
+ uint8_t n = utf8ByteSequenceLength(utf8.at(src_i));
+ size_t next_src_i = src_i + n;
+ uint32_t codepoint = utf8Decode(utf8.slice(src_i, next_src_i));
+ if (codepoint < 0x10000) {
+ utf16_le[dest_i] = codepoint;
+ dest_i += 1;
+ } else {
+ WCHAR high = ((codepoint - 0x10000) >> 10) + 0xD800;
+ WCHAR low = (codepoint & 0x3FF) + 0xDC00;
+ utf16_le[dest_i] = high;
+ utf16_le[dest_i + 1] = low;
+ dest_i += 2;
+ }
+ src_i = next_src_i;
+ }
+ return dest_i;
+}
+
+// Ported from std.os.windows.sliceToPrefixedFileW
+PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
+ PathSpace path_space;
+ for (size_t idx = 0; idx < path.len; idx++) {
+ assert(path.ptr[idx] != '*' && path.ptr[idx] != '?' && path.ptr[idx] != '"' &&
+ path.ptr[idx] != '<' && path.ptr[idx] != '>' && path.ptr[idx] != '|');
+ }
+
+ size_t start_index;
+ if (memStartsWith(path, str("\\?")) || !isAbsoluteWindows(path)) {
+ start_index = 0;
+ } else {
+ static WCHAR prefix[4] = { u'\\', u'?', u'?', u'\\' };
+ memCopy(path_space.data.slice(), Slice<WCHAR> { prefix, 4 });
+ start_index = 4;
+ }
+
+ path_space.len = start_index + utf8_to_utf16le(path_space.data.slice().sliceFrom(start_index).ptr, path);
+ assert(path_space.len <= path_space.data.len);
+
+ Slice<WCHAR> path_slice = path_space.data.slice().slice(0, path_space.len);
+ for (size_t elem_idx = 0; elem_idx < path_slice.len; elem_idx += 1) {
+ if (path_slice.at(elem_idx) == '/') {
+ path_slice.at(elem_idx) = '\\';
+ }
+ }
+
+ path_space.data.items[path_space.len] = 0;
+ return path_space;
+}
#endif
// Ported from std.os.getAppDataDir
@@ -1862,8 +2045,8 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {
#if defined(ZIG_OS_WINDOWS)
- // TODO use CreateFileW
- HANDLE result = CreateFileA(buf_ptr(full_path),
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
+ HANDLE result = CreateFileW(&path_space.data.items[0],
need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,
need_write ? 0 : FILE_SHARE_READ,
nullptr,
@@ -1967,8 +2150,9 @@ Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_
Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
#if defined(ZIG_OS_WINDOWS)
+ PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
for (;;) {
- HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ | GENERIC_WRITE,
+ HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE,
0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (result == INVALID_HANDLE_VALUE) {
diff --git a/src/os.hpp b/src/os.hpp
index e73e5e3aaa..9792a42c45 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -155,4 +155,12 @@ Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname)
Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
+const size_t PATH_MAX_WIDE = 32767;
+
+struct PathSpace {
+ Array<wchar_t, PATH_MAX_WIDE> data;
+ size_t len;
+};
+
+PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path);
#endif
diff --git a/src/parser.cpp b/src/parser.cpp
index c6c5823672..26233ec6a4 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -786,7 +786,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B
return nullptr;
}
-// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
+// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr)
static AstNode *ast_parse_fn_proto(ParseContext *pc) {
Token *first = eat_token_if(pc, TokenIdKeywordFn);
if (first == nullptr) {
@@ -801,10 +801,10 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
AstNode *align_expr = ast_parse_byte_align(pc);
AstNode *section_expr = ast_parse_link_section(pc);
AstNode *callconv_expr = ast_parse_callconv(pc);
- Token *var = eat_token_if(pc, TokenIdKeywordVar);
+ Token *anytype = eat_token_if(pc, TokenIdKeywordAnyType);
Token *exmark = nullptr;
AstNode *return_type = nullptr;
- if (var == nullptr) {
+ if (anytype == nullptr) {
exmark = eat_token_if(pc, TokenIdBang);
return_type = ast_expect(pc, ast_parse_type_expr);
}
@@ -816,7 +816,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
res->data.fn_proto.align_expr = align_expr;
res->data.fn_proto.section_expr = section_expr;
res->data.fn_proto.callconv_expr = callconv_expr;
- res->data.fn_proto.return_var_token = var;
+ res->data.fn_proto.return_anytype_token = anytype;
res->data.fn_proto.auto_err_set = exmark != nullptr;
res->data.fn_proto.return_type = return_type;
@@ -870,9 +870,9 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
AstNode *type_expr = nullptr;
if (eat_token_if(pc, TokenIdColon) != nullptr) {
- Token *var_tok = eat_token_if(pc, TokenIdKeywordVar);
- if (var_tok != nullptr) {
- type_expr = ast_create_node(pc, NodeTypeVarFieldType, var_tok);
+ Token *anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType);
+ if (anytype_tok != nullptr) {
+ type_expr = ast_create_node(pc, NodeTypeAnyTypeField, anytype_tok);
} else {
type_expr = ast_expect(pc, ast_parse_type_expr);
}
@@ -2191,14 +2191,14 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) {
}
// ParamType
-// <- KEYWORD_var
+// <- KEYWORD_anytype
// / DOT3
// / TypeExpr
static AstNode *ast_parse_param_type(ParseContext *pc) {
- Token *var_token = eat_token_if(pc, TokenIdKeywordVar);
- if (var_token != nullptr) {
- AstNode *res = ast_create_node(pc, NodeTypeParamDecl, var_token);
- res->data.param_decl.var_token = var_token;
+ Token *anytype_token = eat_token_if(pc, TokenIdKeywordAnyType);
+ if (anytype_token != nullptr) {
+ AstNode *res = ast_create_node(pc, NodeTypeParamDecl, anytype_token);
+ res->data.param_decl.anytype_token = anytype_token;
return res;
}
@@ -2679,7 +2679,7 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
if (eat_token_if(pc, TokenIdKeywordAlign) != nullptr) {
expect_token(pc, TokenIdLParen);
- AstNode *align_expr = ast_parse_expr(pc);
+ AstNode *align_expr = ast_expect(pc, ast_parse_expr);
child->data.pointer_type.align_expr = align_expr;
if (eat_token_if(pc, TokenIdColon) != nullptr) {
Token *bit_offset_start = expect_token(pc, TokenIdIntLiteral);
@@ -3207,7 +3207,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.suspend.block, visit, context);
break;
case NodeTypeEnumLiteral:
- case NodeTypeVarFieldType:
+ case NodeTypeAnyTypeField:
break;
}
}
diff --git a/src/softfloat_ext.cpp b/src/softfloat_ext.cpp
new file mode 100644
index 0000000000..8408a15116
--- /dev/null
+++ b/src/softfloat_ext.cpp
@@ -0,0 +1,25 @@
+#include "softfloat_ext.hpp"
+
+extern "C" {
+ #include "softfloat.h"
+}
+
+void f128M_abs(const float128_t *aPtr, float128_t *zPtr) {
+ float128_t zero_float;
+ ui32_to_f128M(0, &zero_float);
+ if (f128M_lt(aPtr, &zero_float)) {
+ f128M_sub(&zero_float, aPtr, zPtr);
+ } else {
+ *zPtr = *aPtr;
+ }
+}
+
+void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
+ float128_t zero_float;
+ ui32_to_f128M(0, &zero_float);
+ if (f128M_lt(aPtr, &zero_float)) {
+ f128M_roundToInt(aPtr, softfloat_round_max, false, zPtr);
+ } else {
+ f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
+ }
+} \ No newline at end of file
diff --git a/src/softfloat_ext.hpp b/src/softfloat_ext.hpp
new file mode 100644
index 0000000000..0a1f958933
--- /dev/null
+++ b/src/softfloat_ext.hpp
@@ -0,0 +1,9 @@
+#ifndef ZIG_SOFTFLOAT_EXT_HPP
+#define ZIG_SOFTFLOAT_EXT_HPP
+
+#include "softfloat_types.h"
+
+void f128M_abs(const float128_t *aPtr, float128_t *zPtr);
+void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);
+
+#endif \ No newline at end of file
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index f09a146f2b..487a125d62 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -106,6 +106,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"allowzero", TokenIdKeywordAllowZero},
{"and", TokenIdKeywordAnd},
{"anyframe", TokenIdKeywordAnyFrame},
+ {"anytype", TokenIdKeywordAnyType},
{"asm", TokenIdKeywordAsm},
{"async", TokenIdKeywordAsync},
{"await", TokenIdKeywordAwait},
@@ -1569,6 +1570,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordAlign: return "align";
case TokenIdKeywordAnd: return "and";
case TokenIdKeywordAnyFrame: return "anyframe";
+ case TokenIdKeywordAnyType: return "anytype";
case TokenIdKeywordAsm: return "asm";
case TokenIdKeywordBreak: return "break";
case TokenIdKeywordCatch: return "catch";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index 552ded4ef8..d8af21ee00 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -54,6 +54,7 @@ enum TokenId {
TokenIdKeywordAllowZero,
TokenIdKeywordAnd,
TokenIdKeywordAnyFrame,
+ TokenIdKeywordAnyType,
TokenIdKeywordAsm,
TokenIdKeywordAsync,
TokenIdKeywordAwait,
diff --git a/src/util.hpp b/src/util.hpp
index bd1a5b1e4c..ab8f4c8e70 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -159,7 +159,7 @@ struct Slice {
inline T &at(size_t i) {
assert(i < len);
- return &ptr[i];
+ return ptr[i];
}
inline Slice<T> slice(size_t start, size_t end) {