Merge pull request #4152 from ziglang/ir-clean-up-vars
pay off some result location technical debt with regards to "mem slots"master
commit
76fba5baf9
|
@ -1978,6 +1978,9 @@ pub const LibExeObjStep = struct {
|
||||||
|
|
||||||
const all_features = self.target.getArch().allFeaturesList();
|
const all_features = self.target.getArch().allFeaturesList();
|
||||||
var populated_cpu_features = cross.cpu_features.cpu.features;
|
var populated_cpu_features = cross.cpu_features.cpu.features;
|
||||||
|
if (self.target.getArch().subArchFeature()) |sub_arch_index| {
|
||||||
|
populated_cpu_features.addFeature(sub_arch_index);
|
||||||
|
}
|
||||||
populated_cpu_features.populateDependencies(all_features);
|
populated_cpu_features.populateDependencies(all_features);
|
||||||
|
|
||||||
if (populated_cpu_features.eql(cross.cpu_features.features)) {
|
if (populated_cpu_features.eql(cross.cpu_features.features)) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub const Murmur2_32 = struct {
|
||||||
const m: u32 = 0x5bd1e995;
|
const m: u32 = 0x5bd1e995;
|
||||||
const len = @truncate(u32, str.len);
|
const len = @truncate(u32, str.len);
|
||||||
var h1: u32 = seed ^ len;
|
var h1: u32 = seed ^ len;
|
||||||
for (@ptrCast([*]allowzero align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
|
for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
|
||||||
var k1: u32 = v;
|
var k1: u32 = v;
|
||||||
if (builtin.endian == builtin.Endian.Big)
|
if (builtin.endian == builtin.Endian.Big)
|
||||||
k1 = @byteSwap(u32, k1);
|
k1 = @byteSwap(u32, k1);
|
||||||
|
@ -100,7 +100,7 @@ pub const Murmur2_64 = struct {
|
||||||
const m: u64 = 0xc6a4a7935bd1e995;
|
const m: u64 = 0xc6a4a7935bd1e995;
|
||||||
const len = @as(u64, str.len);
|
const len = @as(u64, str.len);
|
||||||
var h1: u64 = seed ^ (len *% m);
|
var h1: u64 = seed ^ (len *% m);
|
||||||
for (@ptrCast([*]allowzero align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| {
|
for (@ptrCast([*]align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| {
|
||||||
var k1: u64 = v;
|
var k1: u64 = v;
|
||||||
if (builtin.endian == builtin.Endian.Big)
|
if (builtin.endian == builtin.Endian.Big)
|
||||||
k1 = @byteSwap(u64, k1);
|
k1 = @byteSwap(u64, k1);
|
||||||
|
@ -180,7 +180,7 @@ pub const Murmur3_32 = struct {
|
||||||
const c2: u32 = 0x1b873593;
|
const c2: u32 = 0x1b873593;
|
||||||
const len = @truncate(u32, str.len);
|
const len = @truncate(u32, str.len);
|
||||||
var h1: u32 = seed;
|
var h1: u32 = seed;
|
||||||
for (@ptrCast([*]allowzero align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
|
for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
|
||||||
var k1: u32 = v;
|
var k1: u32 = v;
|
||||||
if (builtin.endian == builtin.Endian.Big)
|
if (builtin.endian == builtin.Endian.Big)
|
||||||
k1 = @byteSwap(u32, k1);
|
k1 = @byteSwap(u32, k1);
|
||||||
|
|
|
@ -317,6 +317,7 @@ struct ConstErrValue {
|
||||||
struct ConstBoundFnValue {
|
struct ConstBoundFnValue {
|
||||||
ZigFn *fn;
|
ZigFn *fn;
|
||||||
IrInstGen *first_arg;
|
IrInstGen *first_arg;
|
||||||
|
IrInst *first_arg_src;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConstArgTuple {
|
struct ConstArgTuple {
|
||||||
|
@ -502,6 +503,9 @@ struct ZigValue {
|
||||||
// uncomment these to find bugs. can't leave them uncommented because of a gcc-9 warning
|
// uncomment these to find bugs. can't leave them uncommented because of a gcc-9 warning
|
||||||
//ZigValue(const ZigValue &other) = delete; // plz zero initialize with {}
|
//ZigValue(const ZigValue &other) = delete; // plz zero initialize with {}
|
||||||
//ZigValue& operator= (const ZigValue &other) = delete; // use copy_const_val
|
//ZigValue& operator= (const ZigValue &other) = delete; // use copy_const_val
|
||||||
|
|
||||||
|
// for use in debuggers
|
||||||
|
void dump();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ReturnKnowledge {
|
enum ReturnKnowledge {
|
||||||
|
@ -1256,6 +1260,7 @@ static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1;
|
||||||
struct InferredStructField {
|
struct InferredStructField {
|
||||||
ZigType *inferred_struct_type;
|
ZigType *inferred_struct_type;
|
||||||
Buf *field_name;
|
Buf *field_name;
|
||||||
|
bool already_resolved;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZigTypePointer {
|
struct ZigTypePointer {
|
||||||
|
@ -2262,7 +2267,6 @@ struct ZigVar {
|
||||||
Scope *parent_scope;
|
Scope *parent_scope;
|
||||||
Scope *child_scope;
|
Scope *child_scope;
|
||||||
LLVMValueRef param_value_ref;
|
LLVMValueRef param_value_ref;
|
||||||
size_t mem_slot_index;
|
|
||||||
IrExecutableSrc *owner_exec;
|
IrExecutableSrc *owner_exec;
|
||||||
|
|
||||||
Buf *section_name;
|
Buf *section_name;
|
||||||
|
@ -2283,6 +2287,7 @@ struct ZigVar {
|
||||||
bool is_thread_local;
|
bool is_thread_local;
|
||||||
bool is_comptime_memoized;
|
bool is_comptime_memoized;
|
||||||
bool is_comptime_memoized_value;
|
bool is_comptime_memoized_value;
|
||||||
|
bool did_the_decl_codegen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ErrorTableEntry {
|
struct ErrorTableEntry {
|
||||||
|
|
246
src/analyze.cpp
246
src/analyze.cpp
|
@ -593,9 +593,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inferred_struct_field != nullptr) {
|
if (inferred_struct_field != nullptr) {
|
||||||
entry->abi_size = g->builtin_types.entry_usize->abi_size;
|
entry->abi_size = SIZE_MAX;
|
||||||
entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
|
entry->size_in_bits = SIZE_MAX;
|
||||||
entry->abi_align = g->builtin_types.entry_usize->abi_align;
|
entry->abi_align = UINT32_MAX;
|
||||||
} else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
|
} else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
|
||||||
if (type_has_bits(child_type)) {
|
if (type_has_bits(child_type)) {
|
||||||
entry->abi_size = g->builtin_types.entry_usize->abi_size;
|
entry->abi_size = g->builtin_types.entry_usize->abi_size;
|
||||||
|
@ -1102,11 +1102,28 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
|
||||||
ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
||||||
Buf *type_name, UndefAllowed undef)
|
Buf *type_name, UndefAllowed undef)
|
||||||
{
|
{
|
||||||
|
Error err;
|
||||||
|
|
||||||
|
ZigValue *result = create_const_vals(1);
|
||||||
|
ZigValue *result_ptr = create_const_vals(1);
|
||||||
|
result->special = ConstValSpecialUndef;
|
||||||
|
result->type = (type_entry == nullptr) ? g->builtin_types.entry_var : type_entry;
|
||||||
|
result_ptr->special = ConstValSpecialStatic;
|
||||||
|
result_ptr->type = get_pointer_to_type(g, result->type, false);
|
||||||
|
result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar;
|
||||||
|
result_ptr->data.x_ptr.special = ConstPtrSpecialRef;
|
||||||
|
result_ptr->data.x_ptr.data.ref.pointee = result;
|
||||||
|
|
||||||
size_t backward_branch_count = 0;
|
size_t backward_branch_count = 0;
|
||||||
size_t backward_branch_quota = default_backward_branch_quota;
|
size_t backward_branch_quota = default_backward_branch_quota;
|
||||||
return ir_eval_const_value(g, scope, node, type_entry,
|
if ((err = ir_eval_const_value(g, scope, node, result_ptr,
|
||||||
&backward_branch_count, &backward_branch_quota,
|
&backward_branch_count, &backward_branch_quota,
|
||||||
nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
|
nullptr, nullptr, node, type_name, nullptr, nullptr, undef)))
|
||||||
|
{
|
||||||
|
return g->invalid_inst_gen->value;
|
||||||
|
}
|
||||||
|
destroy(result_ptr, "ZigValue");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,
|
Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,
|
||||||
|
@ -3829,7 +3846,6 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
|
||||||
variable_entry->var_type = var_type;
|
variable_entry->var_type = var_type;
|
||||||
variable_entry->parent_scope = parent_scope;
|
variable_entry->parent_scope = parent_scope;
|
||||||
variable_entry->shadowable = false;
|
variable_entry->shadowable = false;
|
||||||
variable_entry->mem_slot_index = SIZE_MAX;
|
|
||||||
variable_entry->src_arg_index = SIZE_MAX;
|
variable_entry->src_arg_index = SIZE_MAX;
|
||||||
|
|
||||||
assert(name);
|
assert(name);
|
||||||
|
@ -3930,7 +3946,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
|
||||||
|
|
||||||
// TODO more validation for types that can't be used for export/extern variables
|
// TODO more validation for types that can't be used for export/extern variables
|
||||||
ZigType *implicit_type = nullptr;
|
ZigType *implicit_type = nullptr;
|
||||||
if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
|
if (explicit_type != nullptr && explicit_type->id == ZigTypeIdInvalid) {
|
||||||
implicit_type = explicit_type;
|
implicit_type = explicit_type;
|
||||||
} else if (var_decl->expr) {
|
} else if (var_decl->expr) {
|
||||||
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
|
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
|
||||||
|
@ -4718,8 +4734,14 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
|
||||||
assert(!fn_type->data.fn.is_generic);
|
assert(!fn_type->data.fn.is_generic);
|
||||||
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
|
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
|
||||||
|
|
||||||
|
if (fn->analyzed_executable.begin_scope == nullptr) {
|
||||||
|
fn->analyzed_executable.begin_scope = &fn->def_scope->base;
|
||||||
|
}
|
||||||
|
if (fn->analyzed_executable.source_node == nullptr) {
|
||||||
|
fn->analyzed_executable.source_node = fn->body_node;
|
||||||
|
}
|
||||||
ZigType *block_return_type = ir_analyze(g, fn->ir_executable,
|
ZigType *block_return_type = ir_analyze(g, fn->ir_executable,
|
||||||
&fn->analyzed_executable, fn_type_id->return_type, return_type_node);
|
&fn->analyzed_executable, fn_type_id->return_type, return_type_node, nullptr);
|
||||||
fn->src_implicit_return_type = block_return_type;
|
fn->src_implicit_return_type = block_return_type;
|
||||||
|
|
||||||
if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) {
|
if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) {
|
||||||
|
@ -5619,6 +5641,8 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||||
return OnePossibleValueYes;
|
return OnePossibleValueYes;
|
||||||
return type_has_one_possible_value(g, type_entry->data.array.child_type);
|
return type_has_one_possible_value(g, type_entry->data.array.child_type);
|
||||||
case ZigTypeIdStruct:
|
case ZigTypeIdStruct:
|
||||||
|
// If the recursive function call asks, then we are not one possible value.
|
||||||
|
type_entry->one_possible_value = OnePossibleValueNo;
|
||||||
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||||
TypeStructField *field = type_entry->data.structure.fields[i];
|
TypeStructField *field = type_entry->data.structure.fields[i];
|
||||||
OnePossibleValue opv = (field->type_entry != nullptr) ?
|
OnePossibleValue opv = (field->type_entry != nullptr) ?
|
||||||
|
@ -5626,6 +5650,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||||
type_val_resolve_has_one_possible_value(g, field->type_val);
|
type_val_resolve_has_one_possible_value(g, field->type_val);
|
||||||
switch (opv) {
|
switch (opv) {
|
||||||
case OnePossibleValueInvalid:
|
case OnePossibleValueInvalid:
|
||||||
|
type_entry->one_possible_value = OnePossibleValueInvalid;
|
||||||
return OnePossibleValueInvalid;
|
return OnePossibleValueInvalid;
|
||||||
case OnePossibleValueNo:
|
case OnePossibleValueNo:
|
||||||
return OnePossibleValueNo;
|
return OnePossibleValueNo;
|
||||||
|
@ -5633,6 +5658,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
type_entry->one_possible_value = OnePossibleValueYes;
|
||||||
return OnePossibleValueYes;
|
return OnePossibleValueYes;
|
||||||
case ZigTypeIdErrorSet:
|
case ZigTypeIdErrorSet:
|
||||||
case ZigTypeIdEnum:
|
case ZigTypeIdEnum:
|
||||||
|
@ -5678,6 +5704,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||||
assert(field_type != nullptr);
|
assert(field_type != nullptr);
|
||||||
result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
|
result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
|
||||||
}
|
}
|
||||||
|
} else if (result->type->id == ZigTypeIdPointer) {
|
||||||
|
result->data.x_ptr.special = ConstPtrSpecialRef;
|
||||||
|
result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
|
||||||
}
|
}
|
||||||
g->one_possible_values.put(type_entry, result);
|
g->one_possible_values.put(type_entry, result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -6452,7 +6481,21 @@ static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
|
||||||
}
|
}
|
||||||
ty->data.pointer.resolve_loop_flag_zero_bits = true;
|
ty->data.pointer.resolve_loop_flag_zero_bits = true;
|
||||||
|
|
||||||
ZigType *elem_type = ty->data.pointer.child_type;
|
ZigType *elem_type;
|
||||||
|
InferredStructField *isf = ty->data.pointer.inferred_struct_field;
|
||||||
|
if (isf != nullptr) {
|
||||||
|
TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
|
||||||
|
assert(field != nullptr);
|
||||||
|
if (field->is_comptime) {
|
||||||
|
ty->abi_size = 0;
|
||||||
|
ty->size_in_bits = 0;
|
||||||
|
ty->abi_align = 0;
|
||||||
|
return ErrorNone;
|
||||||
|
}
|
||||||
|
elem_type = field->type_entry;
|
||||||
|
} else {
|
||||||
|
elem_type = ty->data.pointer.child_type;
|
||||||
|
}
|
||||||
|
|
||||||
bool has_bits;
|
bool has_bits;
|
||||||
if ((err = type_has_bits2(g, elem_type, &has_bits)))
|
if ((err = type_has_bits2(g, elem_type, &has_bits)))
|
||||||
|
@ -6875,6 +6918,7 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu
|
||||||
}
|
}
|
||||||
case ConstArraySpecialNone: {
|
case ConstArraySpecialNone: {
|
||||||
ZigValue *base = &array->data.s_none.elements[start];
|
ZigValue *base = &array->data.s_none.elements[start];
|
||||||
|
assert(base != nullptr);
|
||||||
assert(start + len <= const_val->type->data.array.len);
|
assert(start + len <= const_val->type->data.array.len);
|
||||||
|
|
||||||
buf_appendf(buf, "%s{", buf_ptr(type_name));
|
buf_appendf(buf, "%s{", buf_ptr(type_name));
|
||||||
|
@ -6890,6 +6934,10 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
|
void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
|
||||||
|
if (const_val == nullptr) {
|
||||||
|
buf_appendf(buf, "(invalid nullptr value)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (const_val->special) {
|
switch (const_val->special) {
|
||||||
case ConstValSpecialRuntime:
|
case ConstValSpecialRuntime:
|
||||||
buf_appendf(buf, "(runtime value)");
|
buf_appendf(buf, "(runtime value)");
|
||||||
|
@ -9295,10 +9343,13 @@ bool type_has_optional_repr(ZigType *ty) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_const_val(ZigValue *dest, ZigValue *src) {
|
void copy_const_val(ZigValue *dest, ZigValue *src) {
|
||||||
|
uint32_t prev_align = dest->llvm_align;
|
||||||
|
ConstParent prev_parent = dest->parent;
|
||||||
memcpy(dest, src, sizeof(ZigValue));
|
memcpy(dest, src, sizeof(ZigValue));
|
||||||
|
dest->llvm_align = prev_align;
|
||||||
if (src->special != ConstValSpecialStatic)
|
if (src->special != ConstValSpecialStatic)
|
||||||
return;
|
return;
|
||||||
dest->parent.id = ConstParentIdNone;
|
dest->parent = prev_parent;
|
||||||
if (dest->type->id == ZigTypeIdStruct) {
|
if (dest->type->id == ZigTypeIdStruct) {
|
||||||
dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
|
dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
|
||||||
for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
|
for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
|
||||||
|
@ -9307,6 +9358,16 @@ void copy_const_val(ZigValue *dest, ZigValue *src) {
|
||||||
dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
|
dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
|
||||||
dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
|
dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
|
||||||
}
|
}
|
||||||
|
} else if (dest->type->id == ZigTypeIdArray) {
|
||||||
|
if (dest->data.x_array.special == ConstArraySpecialNone) {
|
||||||
|
dest->data.x_array.data.s_none.elements = create_const_vals(dest->type->data.array.len);
|
||||||
|
for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) {
|
||||||
|
copy_const_val(&dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]);
|
||||||
|
dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray;
|
||||||
|
dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest;
|
||||||
|
dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
|
} else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
|
||||||
dest->data.x_optional = create_const_vals(1);
|
dest->data.x_optional = create_const_vals(1);
|
||||||
copy_const_val(dest->data.x_optional, src->data.x_optional);
|
copy_const_val(dest->data.x_optional, src->data.x_optional);
|
||||||
|
@ -9353,6 +9414,171 @@ bool type_is_numeric(ZigType *ty) {
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_value_indent(ZigValue *val, int indent) {
|
||||||
|
for (int i = 0; i < indent; i += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Value@%p(", val);
|
||||||
|
if (val->type != nullptr) {
|
||||||
|
fprintf(stderr, "%s)", buf_ptr(&val->type->name));
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "type=nullptr)");
|
||||||
|
}
|
||||||
|
switch (val->special) {
|
||||||
|
case ConstValSpecialUndef:
|
||||||
|
fprintf(stderr, "[undefined]\n");
|
||||||
|
return;
|
||||||
|
case ConstValSpecialLazy:
|
||||||
|
fprintf(stderr, "[lazy]\n");
|
||||||
|
return;
|
||||||
|
case ConstValSpecialRuntime:
|
||||||
|
fprintf(stderr, "[runtime]\n");
|
||||||
|
return;
|
||||||
|
case ConstValSpecialStatic:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (val->type == nullptr)
|
||||||
|
return;
|
||||||
|
switch (val->type->id) {
|
||||||
|
case ZigTypeIdInvalid:
|
||||||
|
fprintf(stderr, "<invalid>\n");
|
||||||
|
return;
|
||||||
|
case ZigTypeIdUnreachable:
|
||||||
|
fprintf(stderr, "<unreachable>\n");
|
||||||
|
return;
|
||||||
|
case ZigTypeIdUndefined:
|
||||||
|
fprintf(stderr, "<undefined>\n");
|
||||||
|
return;
|
||||||
|
case ZigTypeIdVoid:
|
||||||
|
fprintf(stderr, "<{}>\n");
|
||||||
|
return;
|
||||||
|
case ZigTypeIdMetaType:
|
||||||
|
fprintf(stderr, "<%s>\n", buf_ptr(&val->data.x_type->name));
|
||||||
|
return;
|
||||||
|
case ZigTypeIdBool:
|
||||||
|
fprintf(stderr, "<%s>\n", val->data.x_bool ? "true" : "false");
|
||||||
|
return;
|
||||||
|
case ZigTypeIdComptimeInt:
|
||||||
|
case ZigTypeIdInt: {
|
||||||
|
Buf *tmp_buf = buf_alloc();
|
||||||
|
bigint_append_buf(tmp_buf, &val->data.x_bigint, 10);
|
||||||
|
fprintf(stderr, "<%s>\n", buf_ptr(tmp_buf));
|
||||||
|
buf_destroy(tmp_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ZigTypeIdComptimeFloat:
|
||||||
|
case ZigTypeIdFloat:
|
||||||
|
fprintf(stderr, "<TODO dump number>\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ZigTypeIdStruct:
|
||||||
|
fprintf(stderr, "<struct\n");
|
||||||
|
for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
|
||||||
|
for (int j = 0; j < indent; j += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name));
|
||||||
|
if (val->data.x_struct.fields == nullptr) {
|
||||||
|
fprintf(stderr, "<null>\n");
|
||||||
|
} else {
|
||||||
|
dump_value_indent(val->data.x_struct.fields[i], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < indent; i += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, ">\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ZigTypeIdOptional:
|
||||||
|
fprintf(stderr, "<\n");
|
||||||
|
dump_value_indent(val->data.x_optional, indent + 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < indent; i += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, ">\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ZigTypeIdErrorUnion:
|
||||||
|
if (val->data.x_err_union.payload != nullptr) {
|
||||||
|
fprintf(stderr, "<\n");
|
||||||
|
dump_value_indent(val->data.x_err_union.payload, indent + 1);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "<\n");
|
||||||
|
dump_value_indent(val->data.x_err_union.error_set, 0);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < indent; i += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, ">\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ZigTypeIdPointer:
|
||||||
|
switch (val->data.x_ptr.special) {
|
||||||
|
case ConstPtrSpecialInvalid:
|
||||||
|
fprintf(stderr, "<!invalid ptr!>\n");
|
||||||
|
return;
|
||||||
|
case ConstPtrSpecialRef:
|
||||||
|
fprintf(stderr, "<ref\n");
|
||||||
|
dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
|
||||||
|
break;
|
||||||
|
case ConstPtrSpecialBaseStruct: {
|
||||||
|
ZigValue *struct_val = val->data.x_ptr.data.base_struct.struct_val;
|
||||||
|
size_t field_index = val->data.x_ptr.data.base_struct.field_index;
|
||||||
|
fprintf(stderr, "<struct %p field %zu\n", struct_val, field_index);
|
||||||
|
if (struct_val != nullptr) {
|
||||||
|
ZigValue *field_val = struct_val->data.x_struct.fields[field_index];
|
||||||
|
if (field_val != nullptr) {
|
||||||
|
dump_value_indent(field_val, indent + 1);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < indent; i += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, "(invalid null field)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConstPtrSpecialBaseOptionalPayload: {
|
||||||
|
ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
|
||||||
|
fprintf(stderr, "<optional %p payload\n", optional_val);
|
||||||
|
if (optional_val != nullptr) {
|
||||||
|
dump_value_indent(optional_val, indent + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "TODO dump more pointer things\n");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < indent; i += 1) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, ">\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ZigTypeIdVector:
|
||||||
|
case ZigTypeIdArray:
|
||||||
|
case ZigTypeIdNull:
|
||||||
|
case ZigTypeIdErrorSet:
|
||||||
|
case ZigTypeIdEnum:
|
||||||
|
case ZigTypeIdUnion:
|
||||||
|
case ZigTypeIdFn:
|
||||||
|
case ZigTypeIdBoundFn:
|
||||||
|
case ZigTypeIdOpaque:
|
||||||
|
case ZigTypeIdFnFrame:
|
||||||
|
case ZigTypeIdAnyFrame:
|
||||||
|
case ZigTypeIdEnumLiteral:
|
||||||
|
fprintf(stderr, "<TODO dump value>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
zig_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigValue::dump() {
|
||||||
|
dump_value_indent(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// float ops that take a single argument
|
// float ops that take a single argument
|
||||||
//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint
|
//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint
|
||||||
const char *float_op_to_name(BuiltinFnId op) {
|
const char *float_op_to_name(BuiltinFnId op) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "zig_llvm.h"
|
#include "zig_llvm.h"
|
||||||
#include "userland.h"
|
#include "userland.h"
|
||||||
#include "dump_analysis.hpp"
|
#include "dump_analysis.hpp"
|
||||||
|
#include "softfloat.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -3119,8 +3120,14 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executab
|
||||||
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable,
|
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable,
|
||||||
IrInstGenCast *cast_instruction)
|
IrInstGenCast *cast_instruction)
|
||||||
{
|
{
|
||||||
|
Error err;
|
||||||
ZigType *actual_type = cast_instruction->value->value->type;
|
ZigType *actual_type = cast_instruction->value->value->type;
|
||||||
ZigType *wanted_type = cast_instruction->base.value->type;
|
ZigType *wanted_type = cast_instruction->base.value->type;
|
||||||
|
bool wanted_type_has_bits;
|
||||||
|
if ((err = type_has_bits2(g, wanted_type, &wanted_type_has_bits)))
|
||||||
|
codegen_report_errors_and_exit(g);
|
||||||
|
if (!wanted_type_has_bits)
|
||||||
|
return nullptr;
|
||||||
LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
|
LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
|
||||||
ir_assert(expr_val, &cast_instruction->base);
|
ir_assert(expr_val, &cast_instruction->base);
|
||||||
|
|
||||||
|
@ -3498,6 +3505,7 @@ static void render_decl_var(CodeGen *g, ZigVar *var) {
|
||||||
|
|
||||||
static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutableGen *executable, IrInstGenDeclVar *instruction) {
|
static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutableGen *executable, IrInstGenDeclVar *instruction) {
|
||||||
instruction->var->ptr_instruction = instruction->var_ptr;
|
instruction->var->ptr_instruction = instruction->var_ptr;
|
||||||
|
instruction->var->did_the_decl_codegen = true;
|
||||||
render_decl_var(g, instruction->var);
|
render_decl_var(g, instruction->var);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -3966,7 +3974,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {
|
||||||
return;
|
return;
|
||||||
case ScopeIdVarDecl: {
|
case ScopeIdVarDecl: {
|
||||||
ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
|
ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
|
||||||
if (var->ptr_instruction != nullptr) {
|
if (var->did_the_decl_codegen) {
|
||||||
render_decl_var(g, var);
|
render_decl_var(g, var);
|
||||||
}
|
}
|
||||||
// fallthrough
|
// fallthrough
|
||||||
|
@ -4723,6 +4731,10 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutableGen *e
|
||||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||||
}
|
}
|
||||||
if (!type_has_bits(child_type)) {
|
if (!type_has_bits(child_type)) {
|
||||||
|
if (instruction->initializing) {
|
||||||
|
LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
|
||||||
|
gen_store_untyped(g, non_null_bit, base_ptr, 0, false);
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
bool is_scalar = !handle_is_ptr(maybe_type);
|
bool is_scalar = !handle_is_ptr(maybe_type);
|
||||||
|
@ -7529,7 +7541,7 @@ static void do_code_gen(CodeGen *g) {
|
||||||
} else {
|
} else {
|
||||||
if (want_sret) {
|
if (want_sret) {
|
||||||
g->cur_ret_ptr = LLVMGetParam(fn, 0);
|
g->cur_ret_ptr = LLVMGetParam(fn, 0);
|
||||||
} else if (handle_is_ptr(fn_type_id->return_type)) {
|
} else if (type_has_bits(fn_type_id->return_type)) {
|
||||||
g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
|
g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
|
||||||
// TODO add debug info variable for this
|
// TODO add debug info variable for this
|
||||||
} else {
|
} else {
|
||||||
|
|
946
src/ir.cpp
946
src/ir.cpp
File diff suppressed because it is too large
Load Diff
|
@ -16,15 +16,15 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
|
||||||
IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
|
IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
|
||||||
ZigType *var_type, const char *name_hint);
|
ZigType *var_type, const char *name_hint);
|
||||||
|
|
||||||
ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||||
ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
|
ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota,
|
||||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||||
IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
|
IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
|
||||||
|
|
||||||
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val);
|
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val);
|
||||||
|
|
||||||
ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable,
|
ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable,
|
||||||
ZigType *expected_type, AstNode *expected_type_source_node);
|
ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr);
|
||||||
|
|
||||||
bool ir_inst_gen_has_side_effects(IrInstGen *inst);
|
bool ir_inst_gen_has_side_effects(IrInstGen *inst);
|
||||||
bool ir_inst_src_has_side_effects(IrInstSrc *inst);
|
bool ir_inst_src_has_side_effects(IrInstSrc *inst);
|
||||||
|
|
|
@ -12,4 +12,21 @@ extern "C" {
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float16_t zig_double_to_f16(double x) {
|
||||||
|
float64_t y;
|
||||||
|
static_assert(sizeof(x) == sizeof(y), "");
|
||||||
|
memcpy(&y, &x, sizeof(x));
|
||||||
|
return f64_to_f16(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return value is safe to coerce to float even when |x| is NaN or Infinity.
|
||||||
|
static inline double zig_f16_to_double(float16_t x) {
|
||||||
|
float64_t y = f16_to_f64(x);
|
||||||
|
double z;
|
||||||
|
static_assert(sizeof(y) == sizeof(z), "");
|
||||||
|
memcpy(&z, &y, sizeof(y));
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
21
src/util.hpp
21
src/util.hpp
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
#define BREAKPOINT __debugbreak()
|
#define BREAKPOINT __debugbreak()
|
||||||
|
#elif defined(__i386__) || defined(__x86_64__)
|
||||||
|
#define BREAKPOINT __asm__ volatile("int $0x03");
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
#define BREAKPOINT __builtin_debugtrap()
|
#define BREAKPOINT __builtin_debugtrap()
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
@ -49,8 +51,6 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "softfloat.hpp"
|
|
||||||
|
|
||||||
ATTRIBUTE_COLD
|
ATTRIBUTE_COLD
|
||||||
ATTRIBUTE_NORETURN
|
ATTRIBUTE_NORETURN
|
||||||
ATTRIBUTE_PRINTF(1, 2)
|
ATTRIBUTE_PRINTF(1, 2)
|
||||||
|
@ -244,23 +244,6 @@ static inline uint8_t log2_u64(uint64_t x) {
|
||||||
return (63 - clzll(x));
|
return (63 - clzll(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline float16_t zig_double_to_f16(double x) {
|
|
||||||
float64_t y;
|
|
||||||
static_assert(sizeof(x) == sizeof(y), "");
|
|
||||||
memcpy(&y, &x, sizeof(x));
|
|
||||||
return f64_to_f16(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Return value is safe to coerce to float even when |x| is NaN or Infinity.
|
|
||||||
static inline double zig_f16_to_double(float16_t x) {
|
|
||||||
float64_t y = f16_to_f64(x);
|
|
||||||
double z;
|
|
||||||
static_assert(sizeof(y) == sizeof(z), "");
|
|
||||||
memcpy(&z, &y, sizeof(y));
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zig_pretty_print_bytes(FILE *f, double n);
|
void zig_pretty_print_bytes(FILE *f, double n);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -1658,7 +1658,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
cases.addTest("return invalid type from test",
|
cases.addTest("return invalid type from test",
|
||||||
\\test "example" { return 1; }
|
\\test "example" { return 1; }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:25: error: integer value 1 cannot be coerced to type 'void'",
|
"tmp.zig:1:25: error: expected type 'void', found 'comptime_int'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("threadlocal qualifier on const",
|
cases.add("threadlocal qualifier on const",
|
||||||
|
@ -2487,7 +2487,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\ var rule_set = try Foo.init();
|
\\ var rule_set = try Foo.init();
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:2:10: error: expected type 'i32', found 'type'",
|
"tmp.zig:2:19: error: expected type 'i32', found 'type'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("slicing single-item pointer",
|
cases.add("slicing single-item pointer",
|
||||||
|
@ -3393,7 +3393,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\
|
\\
|
||||||
\\fn b() void {}
|
\\fn b() void {}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:3:6: error: unreachable code",
|
"tmp.zig:3:5: error: unreachable code",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("bad import",
|
cases.add("bad import",
|
||||||
|
@ -4011,8 +4011,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\
|
\\
|
||||||
\\export fn entry() usize { return @sizeOf(@TypeOf(Foo)); }
|
\\export fn entry() usize { return @sizeOf(@TypeOf(Foo)); }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:5:25: error: unable to evaluate constant expression",
|
"tmp.zig:5:25: error: cannot store runtime value in compile time variable",
|
||||||
"tmp.zig:2:12: note: referenced here",
|
"tmp.zig:2:12: note: called from here",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("addition with non numbers",
|
cases.add("addition with non numbers",
|
||||||
|
@ -4652,7 +4652,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\fn something() anyerror!void { }
|
\\fn something() anyerror!void { }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:2:5: error: expected type 'void', found 'anyerror'",
|
"tmp.zig:2:5: error: expected type 'void', found 'anyerror'",
|
||||||
"tmp.zig:1:15: note: return type declared here",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("invalid pointer for var type",
|
cases.add("invalid pointer for var type",
|
||||||
|
@ -5743,7 +5742,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\ @export(entry, .{.name = "entry", .linkage = @as(u32, 1234) });
|
\\ @export(entry, .{.name = "entry", .linkage = @as(u32, 1234) });
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:3:50: error: expected type 'std.builtin.GlobalLinkage', found 'u32'",
|
"tmp.zig:3:59: error: expected type 'std.builtin.GlobalLinkage', found 'comptime_int'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("struct with invalid field",
|
cases.add("struct with invalid field",
|
||||||
|
|
|
@ -167,3 +167,23 @@ test "nested bitcast" {
|
||||||
S.foo(42);
|
S.foo(42);
|
||||||
comptime S.foo(42);
|
comptime S.foo(42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "bitcast passed as tuple element" {
|
||||||
|
const S = struct {
|
||||||
|
fn foo(args: var) void {
|
||||||
|
comptime expect(@TypeOf(args[0]) == f32);
|
||||||
|
expect(args[0] == 12.34);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
|
||||||
|
}
|
||||||
|
|
||||||
|
test "triple level result location with bitcast sandwich passed as tuple element" {
|
||||||
|
const S = struct {
|
||||||
|
fn foo(args: var) void {
|
||||||
|
comptime expect(@TypeOf(args[0]) == f64);
|
||||||
|
expect(args[0] > 12.33 and args[0] < 12.35);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
|
||||||
|
}
|
||||||
|
|
|
@ -804,3 +804,16 @@ test "comptime assign int to optional int" {
|
||||||
expectEqual(20, x.?);
|
expectEqual(20, x.?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "return 0 from function that has u0 return type" {
|
||||||
|
const S = struct {
|
||||||
|
fn foo_zero() u0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
comptime {
|
||||||
|
if (S.foo_zero() != 0) {
|
||||||
|
@compileError("test failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ test "const result loc, runtime if cond, else unreachable" {
|
||||||
|
|
||||||
var t = true;
|
var t = true;
|
||||||
const x = if (t) Num.Two else unreachable;
|
const x = if (t) Num.Two else unreachable;
|
||||||
if (x != .Two) @compileError("bad");
|
expect(x == .Two);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "if prongs cast to expected type instead of peer type resolution" {
|
test "if prongs cast to expected type instead of peer type resolution" {
|
||||||
|
|
|
@ -781,3 +781,16 @@ test "pointer to thread local array" {
|
||||||
std.mem.copy(u8, buffer[0..], s);
|
std.mem.copy(u8, buffer[0..], s);
|
||||||
std.testing.expectEqualSlices(u8, buffer[0..], s);
|
std.testing.expectEqualSlices(u8, buffer[0..], s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "auto created variables have correct alignment" {
|
||||||
|
const S = struct {
|
||||||
|
fn foo(str: [*]const u8) u32 {
|
||||||
|
for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
||||||
|
comptime expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
||||||
|
}
|
||||||
|
|
|
@ -153,3 +153,25 @@ test "optional with void type" {
|
||||||
var x = Foo{ .x = null };
|
var x = Foo{ .x = null };
|
||||||
expect(x.x == null);
|
expect(x.x == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "0-bit child type coerced to optional return ptr result location" {
|
||||||
|
const S = struct {
|
||||||
|
fn doTheTest() void {
|
||||||
|
var y = Foo{};
|
||||||
|
var z = y.thing();
|
||||||
|
expect(z != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Foo = struct {
|
||||||
|
pub const Bar = struct {
|
||||||
|
field: *Foo,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn thing(self: *Foo) ?Bar {
|
||||||
|
return Bar{ .field = self };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
S.doTheTest();
|
||||||
|
comptime S.doTheTest();
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const expect = @import("std").testing.expect;
|
const std = @import("std");
|
||||||
const mem = @import("std").mem;
|
const expect = std.testing.expect;
|
||||||
|
const mem = std.mem;
|
||||||
|
|
||||||
fn initStaticArray() [10]i32 {
|
fn initStaticArray() [10]i32 {
|
||||||
var array: [10]i32 = undefined;
|
var array: [10]i32 = undefined;
|
||||||
|
|
Loading…
Reference in New Issue