mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
IR: pointers to constants don't copy data
This commit is contained in:
parent
a55555c99e
commit
62d0d88b56
@ -51,17 +51,24 @@ struct ConstEnumValue {
|
||||
};
|
||||
|
||||
struct ConstStructValue {
|
||||
ConstExprValue **fields;
|
||||
ConstExprValue *fields;
|
||||
};
|
||||
|
||||
struct ConstArrayValue {
|
||||
ConstExprValue **fields;
|
||||
ConstExprValue *elements;
|
||||
// This will be the same as `len` from the type, but we duplicate the information
|
||||
// in the constant value so that pointers pointing to arrays can see this size.
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct ConstPtrValue {
|
||||
ConstExprValue **ptr;
|
||||
// len should almost always be 1. exceptions include C strings
|
||||
uint64_t len;
|
||||
ConstExprValue *base_ptr;
|
||||
// If index is SIZE_MAX, then base_ptr points directly to child type.
|
||||
// Otherwise base_ptr points to an array const val and index is offset
|
||||
// in object units from base_ptr into the block of memory pointed to
|
||||
size_t index;
|
||||
// This flag helps us preserve the null byte when performing compile-time
|
||||
// concatenation on C strings.
|
||||
bool is_c_str;
|
||||
};
|
||||
|
||||
@ -71,15 +78,17 @@ struct ConstErrValue {
|
||||
};
|
||||
|
||||
enum ConstValSpecial {
|
||||
ConstValSpecialOther,
|
||||
ConstValSpecialRuntime,
|
||||
ConstValSpecialStatic,
|
||||
ConstValSpecialUndef,
|
||||
ConstValSpecialZeroes,
|
||||
};
|
||||
|
||||
struct ConstExprValue {
|
||||
bool ok;
|
||||
bool depends_on_compile_var;
|
||||
ConstValSpecial special;
|
||||
bool depends_on_compile_var;
|
||||
LLVMValueRef llvm_value;
|
||||
LLVMValueRef llvm_global;
|
||||
|
||||
// populated if val_type == ConstValTypeOk
|
||||
union {
|
||||
@ -108,13 +117,9 @@ enum ReturnKnowledge {
|
||||
};
|
||||
|
||||
struct Expr {
|
||||
TypeTableEntry *type_entry;
|
||||
IrInstruction *instruction;
|
||||
ReturnKnowledge return_knowledge;
|
||||
VariableTableEntry *variable;
|
||||
|
||||
LLVMValueRef const_llvm_val;
|
||||
ConstExprValue const_val;
|
||||
bool has_global_const;
|
||||
};
|
||||
|
||||
struct StructValExprCodeGen {
|
||||
@ -1289,7 +1294,6 @@ struct CodeGen {
|
||||
// there will not be a corresponding fn_defs entry.
|
||||
ZigList<FnTableEntry *> fn_protos;
|
||||
ZigList<VariableTableEntry *> global_vars;
|
||||
ZigList<AstNode *> global_const_list;
|
||||
|
||||
OutType out_type;
|
||||
FnTableEntry *cur_fn;
|
||||
@ -1733,4 +1737,7 @@ enum LValPurpose {
|
||||
LValPurposeConstAddressOf,
|
||||
};
|
||||
|
||||
static const size_t slice_ptr_index = 0;
|
||||
static const size_t slice_len_index = 1;
|
||||
|
||||
#endif
|
||||
|
||||
@ -882,7 +882,7 @@ static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEnt
|
||||
if (result->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return g->builtin_types.entry_invalid;
|
||||
|
||||
assert(result->static_value.ok);
|
||||
assert(result->static_value.special != ConstValSpecialRuntime);
|
||||
return result->static_value.data.x_type;
|
||||
}
|
||||
|
||||
@ -1963,9 +1963,8 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node
|
||||
}
|
||||
if (implicit_type->id != TypeTableEntryIdInvalid) {
|
||||
Expr *expr = get_resolved_expr(var_decl->expr);
|
||||
assert(result->static_value.ok);
|
||||
expr->const_val = result->static_value;
|
||||
expr->type_entry = result->type_entry;
|
||||
assert(result->static_value.special != ConstValSpecialRuntime);
|
||||
expr->instruction = result;
|
||||
}
|
||||
} else if (!is_extern) {
|
||||
add_node_error(g, node, buf_sprintf("variables must be initialized"));
|
||||
@ -2132,8 +2131,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
|
||||
}
|
||||
|
||||
Expr *expr = get_resolved_expr(literal_node);
|
||||
ConstExprValue *const_val = &expr->const_val;
|
||||
assert(const_val->ok);
|
||||
ConstExprValue *const_val = &expr->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (other_type_underlying->id == TypeTableEntryIdFloat) {
|
||||
return true;
|
||||
} else if (other_type_underlying->id == TypeTableEntryIdInt &&
|
||||
@ -2600,15 +2599,15 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
|
||||
AstNode *use_target_node = src_use_node->data.use.expr;
|
||||
Expr *expr = get_resolved_expr(use_target_node);
|
||||
|
||||
if (expr->type_entry->id == TypeTableEntryIdInvalid) {
|
||||
if (expr->instruction->type_entry->id == TypeTableEntryIdInvalid) {
|
||||
tld->import->any_imports_failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
tld->resolution = TldResolutionOk;
|
||||
|
||||
ConstExprValue *const_val = &expr->const_val;
|
||||
assert(const_val->ok);
|
||||
ConstExprValue *const_val = &expr->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
|
||||
ImportTableEntry *target_import = const_val->data.x_import;
|
||||
assert(target_import);
|
||||
@ -3031,10 +3030,11 @@ void find_libc_lib_path(CodeGen *g) {
|
||||
}
|
||||
|
||||
static uint32_t hash_ptr(void *ptr) {
|
||||
uint64_t x = (uint64_t)(uintptr_t)(ptr);
|
||||
uint32_t a = x >> 32;
|
||||
uint32_t b = x & 0xffffffff;
|
||||
return a ^ b;
|
||||
return ((uintptr_t)ptr) % UINT32_MAX;
|
||||
}
|
||||
|
||||
static uint32_t hash_size(size_t x) {
|
||||
return x % UINT32_MAX;
|
||||
}
|
||||
|
||||
uint32_t fn_type_id_hash(FnTypeId *id) {
|
||||
@ -3090,7 +3090,7 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
return const_val->data.x_bignum.data.x_float * UINT32_MAX;
|
||||
case TypeTableEntryIdPointer:
|
||||
return hash_ptr(const_val->data.x_ptr.ptr);
|
||||
return hash_ptr(const_val->data.x_ptr.base_ptr) + hash_size(const_val->data.x_ptr.index);
|
||||
case TypeTableEntryIdUndefLit:
|
||||
return 162837799;
|
||||
case TypeTableEntryIdNullLit:
|
||||
@ -3143,8 +3143,8 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
|
||||
for (size_t i = 0; i < id->generic_param_count; i += 1) {
|
||||
GenericParamValue *generic_param = &id->generic_params[i];
|
||||
if (generic_param->node) {
|
||||
ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->const_val;
|
||||
assert(const_val->ok);
|
||||
ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
result += hash_const_val(generic_param->type, const_val);
|
||||
}
|
||||
result += hash_ptr(generic_param->type);
|
||||
@ -3160,10 +3160,10 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
|
||||
GenericParamValue *b_val = &b->generic_params[i];
|
||||
if (a_val->type != b_val->type) return false;
|
||||
if (a_val->node && b_val->node) {
|
||||
ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val;
|
||||
ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->const_val;
|
||||
assert(a_const_val->ok);
|
||||
assert(b_const_val->ok);
|
||||
ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->instruction->static_value;
|
||||
ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value;
|
||||
assert(a_const_val->special != ConstValSpecialRuntime);
|
||||
assert(b_const_val->special != ConstValSpecialRuntime);
|
||||
if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
|
||||
return false;
|
||||
}
|
||||
@ -3237,3 +3237,4 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
|
||||
}
|
||||
|
||||
|
||||
|
||||
146
src/codegen.cpp
146
src/codegen.cpp
@ -226,7 +226,8 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
|
||||
g->linker_rdynamic = rdynamic;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
|
||||
static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
|
||||
static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
|
||||
|
||||
static void set_debug_source_node(CodeGen *g, AstNode *node) {
|
||||
assert(node->block_context);
|
||||
@ -862,11 +863,17 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
|
||||
if (!type_has_bits(instruction->type_entry))
|
||||
return nullptr;
|
||||
if (!instruction->llvm_value) {
|
||||
assert(instruction->static_value.ok);
|
||||
assert(instruction->static_value.special != ConstValSpecialRuntime);
|
||||
assert(instruction->type_entry);
|
||||
instruction->llvm_value = gen_const_val(g, instruction->type_entry, &instruction->static_value);
|
||||
render_const_val(g, instruction->type_entry, &instruction->static_value);
|
||||
instruction->llvm_value = instruction->static_value.llvm_value;
|
||||
assert(instruction->llvm_value);
|
||||
}
|
||||
if (instruction->static_value.special != ConstValSpecialRuntime) {
|
||||
if (instruction->type_entry->id == TypeTableEntryIdPointer) {
|
||||
return LLVMBuildLoad(g->builder, instruction->static_value.llvm_global, "");
|
||||
}
|
||||
}
|
||||
return instruction->llvm_value;
|
||||
}
|
||||
|
||||
@ -1401,9 +1408,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
bool want_zeroes = false;
|
||||
|
||||
ConstExprValue *const_val = &init_value->static_value;
|
||||
if (!const_val->ok || const_val->special == ConstValSpecialOther)
|
||||
if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
|
||||
have_init_expr = true;
|
||||
if (const_val->ok && const_val->special == ConstValSpecialZeroes)
|
||||
if (const_val->special == ConstValSpecialZeroes)
|
||||
want_zeroes = true;
|
||||
|
||||
if (have_init_expr) {
|
||||
@ -1740,14 +1747,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
|
||||
assert(const_val->ok);
|
||||
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
zig_unreachable();
|
||||
case ConstValSpecialUndef:
|
||||
return LLVMGetUndef(type_entry->type_ref);
|
||||
case ConstValSpecialZeroes:
|
||||
return LLVMConstNull(type_entry->type_ref);
|
||||
case ConstValSpecialOther:
|
||||
case ConstValSpecialStatic:
|
||||
break;
|
||||
|
||||
}
|
||||
@ -1814,7 +1821,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||
continue;
|
||||
}
|
||||
fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry,
|
||||
const_val->data.x_struct.fields[i]);
|
||||
&const_val->data.x_struct.fields[i]);
|
||||
}
|
||||
return LLVMConstNamedStruct(type_entry->type_ref, fields,
|
||||
type_entry->data.structure.gen_field_count);
|
||||
@ -1829,8 +1836,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||
uint64_t len = type_entry->data.array.len;
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
ConstExprValue *field_value = const_val->data.x_array.fields[i];
|
||||
values[i] = gen_const_val(g, child_type, field_value);
|
||||
ConstExprValue *elem_value = &const_val->data.x_array.elements[i];
|
||||
values[i] = gen_const_val(g, child_type, elem_value);
|
||||
}
|
||||
return LLVMConstArray(child_type->type_ref, values, len);
|
||||
}
|
||||
@ -1878,29 +1885,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||
case TypeTableEntryIdPointer:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.pointer.child_type;
|
||||
size_t len = const_val->data.x_ptr.len;
|
||||
LLVMValueRef target_val;
|
||||
if (len == 1) {
|
||||
target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]);
|
||||
} else if (len > 1) {
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]);
|
||||
}
|
||||
target_val = LLVMConstArray(child_type->type_ref, values, len);
|
||||
} else {
|
||||
return LLVMGetUndef(type_entry->type_ref);
|
||||
}
|
||||
LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), "");
|
||||
LLVMSetInitializer(global_value, target_val);
|
||||
LLVMSetLinkage(global_value, LLVMPrivateLinkage);
|
||||
LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const);
|
||||
LLVMSetUnnamedAddr(global_value, true);
|
||||
|
||||
if (len > 1) {
|
||||
return LLVMConstBitCast(global_value, type_entry->type_ref);
|
||||
render_const_val_global(g, type_entry, const_val);
|
||||
size_t index = const_val->data.x_ptr.index;
|
||||
if (index == SIZE_MAX) {
|
||||
render_const_val(g, child_type, const_val->data.x_ptr.base_ptr);
|
||||
render_const_val_global(g, child_type, const_val->data.x_ptr.base_ptr);
|
||||
return const_val->data.x_ptr.base_ptr->llvm_global;
|
||||
} else {
|
||||
return global_value;
|
||||
ConstExprValue *array_const_val = const_val->data.x_ptr.base_ptr;
|
||||
TypeTableEntry *array_type = get_array_type(g, child_type,
|
||||
array_const_val->data.x_array.size);
|
||||
render_const_val(g, array_type, array_const_val);
|
||||
render_const_val_global(g, array_type, array_const_val);
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(usize->type_ref),
|
||||
LLVMConstInt(usize->type_ref, index, false),
|
||||
};
|
||||
LLVMValueRef ptr_val = LLVMConstInBoundsGEP(array_const_val->llvm_global, indices, 2);
|
||||
return ptr_val;
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
@ -1945,27 +1949,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void gen_const_globals(CodeGen *g) {
|
||||
for (size_t i = 0; i < g->global_const_list.length; i += 1) {
|
||||
AstNode *expr_node = g->global_const_list.at(i);
|
||||
Expr *expr = get_resolved_expr(expr_node);
|
||||
ConstExprValue *const_val = &expr->const_val;
|
||||
assert(const_val->ok);
|
||||
TypeTableEntry *type_entry = expr->type_entry;
|
||||
static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
|
||||
if (!const_val->llvm_value)
|
||||
const_val->llvm_value = gen_const_val(g, type_entry, const_val);
|
||||
|
||||
if (handle_is_ptr(type_entry)) {
|
||||
LLVMValueRef init_val = gen_const_val(g, type_entry, const_val);
|
||||
LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
|
||||
LLVMSetInitializer(global_value, init_val);
|
||||
LLVMSetLinkage(global_value, LLVMPrivateLinkage);
|
||||
LLVMSetGlobalConstant(global_value, true);
|
||||
LLVMSetUnnamedAddr(global_value, true);
|
||||
expr->const_llvm_val = global_value;
|
||||
} else {
|
||||
expr->const_llvm_val = gen_const_val(g, type_entry, const_val);
|
||||
}
|
||||
assert(expr->const_llvm_val);
|
||||
if (const_val->llvm_global)
|
||||
LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
|
||||
}
|
||||
|
||||
static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
|
||||
if (!const_val->llvm_global) {
|
||||
LLVMValueRef global_value = LLVMAddGlobal(g->module, type_entry->type_ref, "");
|
||||
LLVMSetLinkage(global_value, LLVMInternalLinkage);
|
||||
LLVMSetGlobalConstant(global_value, true);
|
||||
LLVMSetUnnamedAddr(global_value, true);
|
||||
|
||||
const_val->llvm_global = global_value;
|
||||
}
|
||||
|
||||
if (const_val->llvm_value)
|
||||
LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
|
||||
}
|
||||
|
||||
static void delete_unused_builtin_fns(CodeGen *g) {
|
||||
@ -2096,9 +2099,6 @@ static void do_code_gen(CodeGen *g) {
|
||||
assert(!g->errors.length);
|
||||
|
||||
delete_unused_builtin_fns(g);
|
||||
|
||||
|
||||
gen_const_globals(g);
|
||||
generate_error_name_table(g);
|
||||
|
||||
// Generate module level variables
|
||||
@ -2107,8 +2107,8 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
if (var->type->id == TypeTableEntryIdNumLitFloat) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
|
||||
assert(const_val->ok);
|
||||
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
TypeTableEntry *var_type = g->builtin_types.entry_f64;
|
||||
LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);
|
||||
gen_global_var(g, var, init_val, var_type);
|
||||
@ -2117,8 +2117,8 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
if (var->type->id == TypeTableEntryIdNumLitInt) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
|
||||
assert(const_val->ok);
|
||||
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
|
||||
g->builtin_types.entry_isize : g->builtin_types.entry_usize;
|
||||
LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,
|
||||
@ -2143,25 +2143,13 @@ static void do_code_gen(CodeGen *g) {
|
||||
LLVMSetLinkage(global_value, LLVMExternalLinkage);
|
||||
} else {
|
||||
AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
|
||||
LLVMValueRef init_val;
|
||||
if (expr_node) {
|
||||
Expr *expr = get_resolved_expr(expr_node);
|
||||
ConstExprValue *const_val = &expr->const_val;
|
||||
assert(const_val->ok);
|
||||
TypeTableEntry *type_entry = expr->type_entry;
|
||||
init_val = gen_const_val(g, type_entry, const_val);
|
||||
} else {
|
||||
init_val = LLVMConstNull(var->type->type_ref);
|
||||
}
|
||||
|
||||
global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), buf_ptr(&var->name));
|
||||
LLVMSetInitializer(global_value, init_val);
|
||||
LLVMSetLinkage(global_value, LLVMInternalLinkage);
|
||||
LLVMSetUnnamedAddr(global_value, true);
|
||||
|
||||
IrInstruction *instruction = get_resolved_expr(expr_node)->instruction;
|
||||
render_const_val(g, instruction->type_entry, &instruction->static_value);
|
||||
render_const_val_global(g, instruction->type_entry, &instruction->static_value);
|
||||
global_value = instruction->static_value.llvm_global;
|
||||
// TODO debug info for function pointers
|
||||
if (var->gen_is_const && var->type->id != TypeTableEntryIdFn) {
|
||||
gen_global_var(g, var, init_val, var->type);
|
||||
gen_global_var(g, var, instruction->static_value.llvm_value, var->type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3282,11 +3270,11 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
|
||||
|
||||
static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {
|
||||
Expr *expr = get_resolved_expr(type_node);
|
||||
assert(expr->type_entry);
|
||||
assert(expr->type_entry->id == TypeTableEntryIdMetaType);
|
||||
assert(expr->instruction->type_entry);
|
||||
assert(expr->instruction->type_entry->id == TypeTableEntryIdMetaType);
|
||||
|
||||
ConstExprValue *const_val = &expr->const_val;
|
||||
assert(const_val->ok);
|
||||
ConstExprValue *const_val = &expr->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
|
||||
TypeTableEntry *type_entry = const_val->data.x_type;
|
||||
|
||||
|
||||
119
src/eval.cpp
119
src/eval.cpp
@ -147,7 +147,7 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
|
||||
}
|
||||
}
|
||||
|
||||
out_val->ok = true;
|
||||
out_val->special = ConstValSpecialStatic;
|
||||
out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
||||
return 0;
|
||||
}
|
||||
@ -155,8 +155,8 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
|
||||
int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
|
||||
BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
|
||||
{
|
||||
assert(op1_val->ok);
|
||||
assert(op2_val->ok);
|
||||
assert(op1_val->special != ConstValSpecialRuntime);
|
||||
assert(op2_val->special != ConstValSpecialRuntime);
|
||||
assert(op1_type->id != TypeTableEntryIdInvalid);
|
||||
assert(op2_type->id != TypeTableEntryIdInvalid);
|
||||
|
||||
@ -171,7 +171,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
|
||||
assert(op1_type->id == TypeTableEntryIdBool);
|
||||
assert(op2_type->id == TypeTableEntryIdBool);
|
||||
out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);
|
||||
out_val->ok = true;
|
||||
out_val->special = ConstValSpecialStatic;
|
||||
out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
||||
return 0;
|
||||
case BinOpTypeCmpEq:
|
||||
@ -219,7 +219,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
|
||||
out_val->depends_on_compile_var =
|
||||
op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
||||
out_val->data.x_bool = answer;
|
||||
out_val->ok = true;
|
||||
out_val->special = ConstValSpecialStatic;
|
||||
return 0;
|
||||
}
|
||||
case BinOpTypeAdd:
|
||||
@ -309,67 +309,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
|
||||
*const_val = *other_val;
|
||||
break;
|
||||
case CastOpPointerReinterpret:
|
||||
if (other_type->id == TypeTableEntryIdPointer &&
|
||||
new_type->id == TypeTableEntryIdPointer)
|
||||
{
|
||||
TypeTableEntry *other_child_type = other_type->data.pointer.child_type;
|
||||
TypeTableEntry *new_child_type = new_type->data.pointer.child_type;
|
||||
|
||||
if ((other_child_type->id == TypeTableEntryIdInt ||
|
||||
other_child_type->id == TypeTableEntryIdFloat) &&
|
||||
(new_child_type->id == TypeTableEntryIdInt ||
|
||||
new_child_type->id == TypeTableEntryIdFloat))
|
||||
{
|
||||
ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
|
||||
*ptr_val = other_val->data.x_ptr.ptr[0];
|
||||
const_val->data.x_ptr.ptr = ptr_val;
|
||||
const_val->data.x_ptr.len = 1;
|
||||
const_val->ok = true;
|
||||
const_val->special = other_val->special;
|
||||
const_val->depends_on_compile_var = other_val->depends_on_compile_var;
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
} else if (other_type->id == TypeTableEntryIdMaybe &&
|
||||
new_type->id == TypeTableEntryIdMaybe)
|
||||
{
|
||||
if (!other_val->data.x_maybe) {
|
||||
*const_val = *other_val;
|
||||
break;
|
||||
}
|
||||
|
||||
TypeTableEntry *other_ptr_type = other_type->data.maybe.child_type;
|
||||
TypeTableEntry *new_ptr_type = new_type->data.maybe.child_type;
|
||||
|
||||
if (other_ptr_type->id == TypeTableEntryIdPointer &&
|
||||
new_ptr_type->id == TypeTableEntryIdPointer)
|
||||
{
|
||||
TypeTableEntry *other_child_type = other_ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *new_child_type = new_ptr_type->data.pointer.child_type;
|
||||
|
||||
if ((other_child_type->id == TypeTableEntryIdInt ||
|
||||
other_child_type->id == TypeTableEntryIdFloat) &&
|
||||
(new_child_type->id == TypeTableEntryIdInt ||
|
||||
new_child_type->id == TypeTableEntryIdFloat))
|
||||
{
|
||||
ConstExprValue *ptr_parent = allocate<ConstExprValue>(1);
|
||||
ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
|
||||
*ptr_val = other_val->data.x_maybe->data.x_ptr.ptr[0];
|
||||
ptr_parent->data.x_ptr.ptr = ptr_val;
|
||||
ptr_parent->data.x_ptr.len = 1;
|
||||
ptr_parent->ok = true;
|
||||
|
||||
const_val->data.x_maybe = ptr_parent;
|
||||
const_val->ok = true;
|
||||
const_val->special = other_val->special;
|
||||
const_val->depends_on_compile_var = other_val->depends_on_compile_var;
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
}
|
||||
zig_panic("TODO compile time pointer reinterpret");
|
||||
break;
|
||||
case CastOpPtrToInt:
|
||||
case CastOpIntToPtr:
|
||||
@ -378,62 +318,43 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
|
||||
// can't do it
|
||||
break;
|
||||
case CastOpToUnknownSizeArray:
|
||||
{
|
||||
assert(other_type->id == TypeTableEntryIdArray);
|
||||
|
||||
ConstExprValue *all_fields = allocate<ConstExprValue>(2);
|
||||
ConstExprValue *ptr_field = &all_fields[0];
|
||||
ConstExprValue *len_field = &all_fields[1];
|
||||
|
||||
const_val->data.x_struct.fields = allocate<ConstExprValue*>(2);
|
||||
const_val->data.x_struct.fields[0] = ptr_field;
|
||||
const_val->data.x_struct.fields[1] = len_field;
|
||||
|
||||
ptr_field->ok = true;
|
||||
ptr_field->data.x_ptr.ptr = other_val->data.x_array.fields;
|
||||
ptr_field->data.x_ptr.len = other_type->data.array.len;
|
||||
|
||||
len_field->ok = true;
|
||||
bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
|
||||
|
||||
const_val->ok = true;
|
||||
break;
|
||||
}
|
||||
zig_panic("TODO compile time implicit to unknown size array");
|
||||
break;
|
||||
case CastOpMaybeWrap:
|
||||
const_val->data.x_maybe = other_val;
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpNullToMaybe:
|
||||
const_val->data.x_maybe = nullptr;
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpErrorWrap:
|
||||
const_val->data.x_err.err = nullptr;
|
||||
const_val->data.x_err.payload = other_val;
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpPureErrorWrap:
|
||||
const_val->data.x_err.err = other_val->data.x_err.err;
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpErrToInt:
|
||||
{
|
||||
uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, value);
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
}
|
||||
case CastOpIntToFloat:
|
||||
bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpFloatToInt:
|
||||
bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpBoolToInt:
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
case CastOpIntToEnum:
|
||||
{
|
||||
@ -442,12 +363,12 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
|
||||
assert(value < new_type->data.enumeration.src_field_count);
|
||||
const_val->data.x_enum.tag = value;
|
||||
const_val->data.x_enum.payload = NULL;
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
}
|
||||
case CastOpEnumToInt:
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -465,7 +386,7 @@ static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type
|
||||
|
||||
void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
|
||||
if (type_entry->id == TypeTableEntryIdInt) {
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
|
||||
if (is_max) {
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
@ -486,7 +407,7 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
zig_panic("TODO analyze_min_max_value float");
|
||||
} else if (type_entry->id == TypeTableEntryIdBool) {
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->data.x_bool = is_max;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
|
||||
221
src/ir.cpp
221
src/ir.cpp
@ -35,6 +35,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
|
||||
LValPurpose lval);
|
||||
static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
|
||||
|
||||
ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
|
||||
ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
|
||||
size_t index = const_val->data.x_ptr.index;
|
||||
|
||||
if (index == SIZE_MAX) {
|
||||
return base_ptr;
|
||||
} else {
|
||||
assert(index < base_ptr->data.x_array.size);
|
||||
return &base_ptr->data.x_array.elements[index];
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
|
||||
assert(basic_block);
|
||||
assert(instruction);
|
||||
@ -237,7 +249,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
|
||||
{
|
||||
IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);
|
||||
cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
|
||||
cond_br_instruction->base.static_value.ok = true;
|
||||
cond_br_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
cond_br_instruction->condition = condition;
|
||||
cond_br_instruction->then_block = then_block;
|
||||
cond_br_instruction->else_block = else_block;
|
||||
@ -262,7 +274,7 @@ static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_i
|
||||
static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {
|
||||
IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);
|
||||
return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
|
||||
return_instruction->base.static_value.ok = true;
|
||||
return_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
return_instruction->value = return_value;
|
||||
|
||||
ir_ref_instruction(return_value);
|
||||
@ -281,20 +293,19 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in
|
||||
static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
|
||||
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
|
||||
const_instruction->base.type_entry = type_entry;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_const_undefined(IrBuilder *irb, AstNode *source_node) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialUndef;
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_undef;
|
||||
return &const_instruction->base;
|
||||
@ -304,7 +315,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ?
|
||||
irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_bignum = *bignum;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -312,7 +323,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
|
||||
static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, uint64_t value) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_usize;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
bignum_init_unsigned(&const_instruction->base.static_value.data.x_bignum, value);
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -320,7 +331,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node,
|
||||
static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
|
||||
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_type = type_entry;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -334,7 +345,7 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node,
|
||||
static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = fn_entry->type_entry;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_fn = fn_entry;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -342,7 +353,7 @@ static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, Fn
|
||||
static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = fn_type;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_type = fn_type;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -350,7 +361,7 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_
|
||||
static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node, ImportTableEntry *import) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_namespace;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_import = import;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -358,7 +369,7 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node
|
||||
static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, BlockContext *scope) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_block;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_block = scope;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -366,7 +377,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node,
|
||||
static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
const_instruction->base.type_entry = irb->codegen->builtin_types.entry_bool;
|
||||
const_instruction->base.static_value.ok = true;
|
||||
const_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.static_value.data.x_bool = value;
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -377,45 +388,45 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_nod
|
||||
TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str));
|
||||
const_instruction->base.type_entry = type_entry;
|
||||
ConstExprValue *const_val = &const_instruction->base.static_value;
|
||||
const_val->ok = true;
|
||||
const_val->data.x_array.fields = allocate<ConstExprValue*>(buf_len(str));
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str));
|
||||
const_val->data.x_array.size = buf_len(str);
|
||||
|
||||
ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str));
|
||||
for (size_t i = 0; i < buf_len(str); i += 1) {
|
||||
ConstExprValue *this_char = &all_chars[i];
|
||||
this_char->ok = true;
|
||||
ConstExprValue *this_char = &const_val->data.x_array.elements[i];
|
||||
this_char->special = ConstValSpecialStatic;
|
||||
bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
|
||||
const_val->data.x_array.fields[i] = this_char;
|
||||
}
|
||||
|
||||
return &const_instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) {
|
||||
// first we build the underlying array
|
||||
size_t len_with_null = buf_len(str) + 1;
|
||||
ConstExprValue *array_val = allocate<ConstExprValue>(1);
|
||||
array_val->special = ConstValSpecialStatic;
|
||||
array_val->data.x_array.elements = allocate<ConstExprValue>(len_with_null);
|
||||
array_val->data.x_array.size = len_with_null;
|
||||
for (size_t i = 0; i < buf_len(str); i += 1) {
|
||||
ConstExprValue *this_char = &array_val->data.x_array.elements[i];
|
||||
this_char->special = ConstValSpecialStatic;
|
||||
bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
|
||||
}
|
||||
ConstExprValue *null_char = &array_val->data.x_array.elements[len_with_null - 1];
|
||||
null_char->special = ConstValSpecialStatic;
|
||||
bignum_init_unsigned(&null_char->data.x_bignum, 0);
|
||||
|
||||
// then make the pointer point to it
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
|
||||
TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8;
|
||||
TypeTableEntry *type_entry = get_pointer_to_type(irb->codegen, u8_type, true);
|
||||
const_instruction->base.type_entry = type_entry;
|
||||
ConstExprValue *const_val = &const_instruction->base.static_value;
|
||||
const_val->ok = true;
|
||||
|
||||
size_t len_with_null = buf_len(str) + 1;
|
||||
const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null);
|
||||
const_val->data.x_ptr.len = len_with_null;
|
||||
const_val->data.x_ptr.is_c_str = true;
|
||||
|
||||
ConstExprValue *all_chars = allocate<ConstExprValue>(len_with_null);
|
||||
for (size_t i = 0; i < buf_len(str); i += 1) {
|
||||
ConstExprValue *this_char = &all_chars[i];
|
||||
this_char->ok = true;
|
||||
bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
|
||||
const_val->data.x_ptr.ptr[i] = this_char;
|
||||
}
|
||||
|
||||
ConstExprValue *null_char = &all_chars[len_with_null - 1];
|
||||
null_char->ok = true;
|
||||
bignum_init_unsigned(&null_char->data.x_bignum, 0);
|
||||
const_val->data.x_ptr.ptr[len_with_null - 1] = null_char;
|
||||
ConstExprValue *ptr_val = &const_instruction->base.static_value;
|
||||
ptr_val->special = ConstValSpecialStatic;
|
||||
ptr_val->data.x_ptr.base_ptr = array_val;
|
||||
ptr_val->data.x_ptr.index = 0;
|
||||
ptr_val->data.x_ptr.is_c_str = true;
|
||||
|
||||
return &const_instruction->base;
|
||||
}
|
||||
@ -591,7 +602,7 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
|
||||
static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) {
|
||||
IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
|
||||
br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
|
||||
br_instruction->base.static_value.ok = true;
|
||||
br_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
br_instruction->dest_block = dest_block;
|
||||
br_instruction->is_inline = is_inline;
|
||||
|
||||
@ -662,7 +673,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *so
|
||||
static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) {
|
||||
IrInstructionUnreachable *unreachable_instruction =
|
||||
ir_build_instruction<IrInstructionUnreachable>(irb, source_node);
|
||||
unreachable_instruction->base.static_value.ok = true;
|
||||
unreachable_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
|
||||
return &unreachable_instruction->base;
|
||||
}
|
||||
@ -677,7 +688,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,
|
||||
IrInstruction *ptr, IrInstruction *value)
|
||||
{
|
||||
IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node);
|
||||
instruction->base.static_value.ok = true;
|
||||
instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
|
||||
instruction->ptr = ptr;
|
||||
instruction->value = value;
|
||||
@ -700,7 +711,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
|
||||
VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)
|
||||
{
|
||||
IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, source_node);
|
||||
decl_var_instruction->base.static_value.ok = true;
|
||||
decl_var_instruction->base.static_value.special = ConstValSpecialStatic;
|
||||
decl_var_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
|
||||
decl_var_instruction->var = var;
|
||||
decl_var_instruction->var_type = var_type;
|
||||
@ -1900,7 +1911,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
||||
}
|
||||
|
||||
ConstExprValue *const_val = &instruction->static_value;
|
||||
assert(const_val->ok);
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (other_type_underlying->id == TypeTableEntryIdFloat) {
|
||||
return true;
|
||||
} else if (other_type_underlying->id == TypeTableEntryIdInt &&
|
||||
@ -2110,10 +2121,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
IrInstruction *dest_type, CastOp cast_op, bool need_alloca)
|
||||
{
|
||||
assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
|
||||
assert(dest_type->static_value.ok);
|
||||
assert(dest_type->static_value.special != ConstValSpecialRuntime);
|
||||
TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
|
||||
|
||||
if (value->static_value.ok) {
|
||||
if (value->static_value.special != ConstValSpecialRuntime) {
|
||||
IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type);
|
||||
eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,
|
||||
&result->static_value, wanted_type);
|
||||
@ -2194,7 +2205,7 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in
|
||||
}
|
||||
ir_link_new_instruction(new_instruction, old_instruction);
|
||||
ConstExprValue *const_val = &new_instruction->static_value;
|
||||
const_val->ok = true;
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->depends_on_compile_var = depends_on_compile_var;
|
||||
return const_val;
|
||||
}
|
||||
@ -2226,7 +2237,7 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
|
||||
}
|
||||
|
||||
ConstExprValue *const_val = &type_value->static_value;
|
||||
if (!const_val->ok) {
|
||||
if (const_val->special == ConstValSpecialRuntime) {
|
||||
add_node_error(ira->codegen, type_value->source_node,
|
||||
buf_sprintf("unable to evaluate constant expression"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
@ -2249,7 +2260,7 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out
|
||||
}
|
||||
|
||||
ConstExprValue *const_val = &bool_value->static_value;
|
||||
if (!const_val->ok) {
|
||||
if (const_val->special == ConstValSpecialRuntime) {
|
||||
add_node_error(ira->codegen, bool_value->source_node,
|
||||
buf_sprintf("unable to evaluate constant expression"));
|
||||
return false;
|
||||
@ -2273,7 +2284,7 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
|
||||
}
|
||||
|
||||
ConstExprValue *const_val = &fn_value->static_value;
|
||||
if (!const_val->ok) {
|
||||
if (const_val->special == ConstValSpecialRuntime) {
|
||||
add_node_error(ira->codegen, fn_value->source_node,
|
||||
buf_sprintf("unable to evaluate constant expression"));
|
||||
return nullptr;
|
||||
@ -2286,7 +2297,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
IrInstruction *dest_type, IrInstruction *value)
|
||||
{
|
||||
assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
|
||||
assert(dest_type->static_value.ok);
|
||||
assert(dest_type->static_value.special != ConstValSpecialRuntime);
|
||||
|
||||
TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
|
||||
TypeTableEntry *actual_type = value->type_entry;
|
||||
@ -2618,7 +2629,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
|
||||
|
||||
ConstExprValue *op1_val = &casted_op1->static_value;
|
||||
ConstExprValue *op2_val = &casted_op2->static_value;
|
||||
if (op1_val->ok && op2_val->ok) {
|
||||
if (op1_val->special != ConstValSpecialRuntime && op2_val->special != ConstValSpecialRuntime) {
|
||||
bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var);
|
||||
|
||||
@ -2710,7 +2721,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
|
||||
|
||||
ConstExprValue *op1_val = &casted_op1->static_value;
|
||||
ConstExprValue *op2_val = &casted_op2->static_value;
|
||||
if (op1_val->ok && op2_val->ok) {
|
||||
if (op1_val->special != ConstValSpecialRuntime && op2_val->special != ConstValSpecialRuntime) {
|
||||
bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||
|
||||
resolved_type->id == TypeTableEntryIdNumLitInt ||
|
||||
resolved_type->id == TypeTableEntryIdFloat ||
|
||||
@ -2799,7 +2810,7 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
|
||||
}
|
||||
}
|
||||
|
||||
out_val->ok = true;
|
||||
out_val->special = ConstValSpecialStatic;
|
||||
out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
|
||||
return 0;
|
||||
}
|
||||
@ -2892,7 +2903,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
|
||||
if (casted_op1->static_value.ok && casted_op2->static_value.ok) {
|
||||
if (casted_op1->static_value.special != ConstValSpecialRuntime && casted_op2->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *op1_val = &casted_op1->static_value;
|
||||
ConstExprValue *op2_val = &casted_op2->static_value;
|
||||
ConstExprValue *out_val = &bin_op_instruction->base.static_value;
|
||||
@ -2992,7 +3003,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
|
||||
break;
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
if (is_export || is_extern || !casted_init_value->static_value.ok) {
|
||||
if (is_export || is_extern || casted_init_value->static_value.special == ConstValSpecialRuntime) {
|
||||
add_node_error(ira->codegen, var_type->source_node, buf_sprintf("unable to infer variable type"));
|
||||
result_type = ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -3006,7 +3017,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
|
||||
break;
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdNamespace:
|
||||
if (!casted_init_value->static_value.ok) {
|
||||
if (casted_init_value->static_value.special == ConstValSpecialRuntime) {
|
||||
add_node_error(ira->codegen, var_type->source_node,
|
||||
buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
|
||||
result_type = ira->codegen->builtin_types.entry_invalid;
|
||||
@ -3052,7 +3063,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
|
||||
if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (fn_ref->static_value.ok) {
|
||||
if (fn_ref->static_value.special != ConstValSpecialRuntime) {
|
||||
if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {
|
||||
size_t actual_param_count = call_instruction->arg_count;
|
||||
|
||||
@ -3106,9 +3117,9 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
ConstExprValue *operand_val = &casted_value->static_value;
|
||||
if (operand_val->ok) {
|
||||
if (operand_val->special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *result_val = &un_op_instruction->base.static_value;
|
||||
result_val->ok = true;
|
||||
result_val->special = ConstValSpecialStatic;
|
||||
result_val->depends_on_compile_var = operand_val->depends_on_compile_var;
|
||||
result_val->data.x_bool = !operand_val->data.x_bool;
|
||||
return bool_type;
|
||||
@ -3204,7 +3215,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
|
||||
value->static_value.depends_on_compile_var);
|
||||
assert(value->static_value.ok);
|
||||
assert(value->static_value.special != ConstValSpecialRuntime);
|
||||
TypeTableEntry *child_type = value->static_value.data.x_type;
|
||||
out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);
|
||||
return ira->codegen->builtin_types.entry_type;
|
||||
@ -3252,9 +3263,10 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
|
||||
// this dereference is always an rvalue because in the IR gen we identify lvalue and emit
|
||||
// one of the ptr instructions
|
||||
|
||||
if (value->static_value.ok) {
|
||||
if (value->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, false);
|
||||
*out_val = *value->static_value.data.x_ptr.ptr[0];
|
||||
ConstExprValue *pointee = const_ptr_pointee(&value->static_value);
|
||||
*out_val = *pointee;
|
||||
return child_type;
|
||||
}
|
||||
|
||||
@ -3428,7 +3440,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
|
||||
return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
|
||||
|
||||
// TODO detect backward jumps
|
||||
if (condition->static_value.ok) {
|
||||
if (condition->static_value.special != ConstValSpecialRuntime) {
|
||||
IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?
|
||||
cond_br_instruction->then_block : cond_br_instruction->else_block;
|
||||
|
||||
@ -3463,7 +3475,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
|
||||
continue;
|
||||
IrInstruction *value = phi_instruction->incoming_values[i]->other;
|
||||
assert(value->type_entry);
|
||||
if (value->static_value.ok) {
|
||||
if (value->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,
|
||||
value->static_value.depends_on_compile_var);
|
||||
*out_val = value->static_value;
|
||||
@ -3523,17 +3535,16 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
|
||||
} else if (var->src_is_const) {
|
||||
AstNode *var_decl_node = var->decl_node;
|
||||
assert(var_decl_node->type == NodeTypeVariableDeclaration);
|
||||
mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->const_val;
|
||||
assert(mem_slot->ok);
|
||||
mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->instruction->static_value;
|
||||
assert(mem_slot->special != ConstValSpecialRuntime);
|
||||
}
|
||||
|
||||
if (mem_slot && mem_slot->ok) {
|
||||
if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base,
|
||||
mem_slot->depends_on_compile_var);
|
||||
|
||||
out_val->data.x_ptr.len = 1;
|
||||
out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
|
||||
out_val->data.x_ptr.ptr[0] = mem_slot;
|
||||
out_val->data.x_ptr.base_ptr = mem_slot;
|
||||
out_val->data.x_ptr.index = SIZE_MAX;
|
||||
return ptr_type;
|
||||
} else {
|
||||
ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var);
|
||||
@ -3577,7 +3588,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
if (casted_elem_index == ira->codegen->invalid_instruction)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (casted_elem_index->static_value.ok) {
|
||||
if (casted_elem_index->static_value.special != ConstValSpecialRuntime) {
|
||||
uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
uint64_t array_len = array_type->data.array.len;
|
||||
@ -3589,24 +3600,34 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
}
|
||||
}
|
||||
|
||||
if (array_ptr->static_value.ok) {
|
||||
if (array_ptr->static_value.special != ConstValSpecialRuntime) {
|
||||
bool depends_on_compile_var = array_ptr->static_value.depends_on_compile_var ||
|
||||
casted_elem_index->static_value.depends_on_compile_var;
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var);
|
||||
out_val->data.x_ptr.len = 1;
|
||||
out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len;
|
||||
if (index >= pointer_len) {
|
||||
size_t offset = array_ptr->static_value.data.x_ptr.index;
|
||||
size_t new_index;
|
||||
size_t mem_size;
|
||||
size_t old_size;
|
||||
if (offset == SIZE_MAX) {
|
||||
new_index = SIZE_MAX;
|
||||
mem_size = 1;
|
||||
old_size = 1;
|
||||
} else {
|
||||
new_index = offset + index;
|
||||
mem_size = array_ptr->static_value.data.x_ptr.base_ptr->data.x_array.size;
|
||||
old_size = mem_size - offset;
|
||||
}
|
||||
if (new_index >= mem_size) {
|
||||
add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
|
||||
buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64,
|
||||
index, pointer_len));
|
||||
buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, index, old_size));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_ptr.ptr[index];
|
||||
out_val->data.x_ptr.base_ptr = array_ptr->static_value.data.x_ptr.base_ptr;
|
||||
out_val->data.x_ptr.index = new_index;
|
||||
} else if (is_slice(array_type)) {
|
||||
ConstExprValue *ptr_field = array_ptr->static_value.data.x_struct.fields[0];
|
||||
ConstExprValue *len_field = array_ptr->static_value.data.x_struct.fields[1];
|
||||
ConstExprValue *ptr_field = &array_ptr->static_value.data.x_struct.fields[slice_ptr_index];
|
||||
ConstExprValue *len_field = &array_ptr->static_value.data.x_struct.fields[slice_len_index];
|
||||
uint64_t slice_len = len_field->data.x_bignum.data.x_uint;
|
||||
if (index >= slice_len) {
|
||||
add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
|
||||
@ -3614,10 +3635,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
index, slice_len));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
assert(index < ptr_field->data.x_ptr.len);
|
||||
out_val->data.x_ptr.ptr[0] = ptr_field->data.x_ptr.ptr[index];
|
||||
out_val->data.x_ptr.base_ptr = ptr_field->data.x_ptr.base_ptr;
|
||||
size_t offset = ptr_field->data.x_ptr.index;
|
||||
if (offset == SIZE_MAX) {
|
||||
out_val->data.x_ptr.index = SIZE_MAX;
|
||||
} else {
|
||||
uint64_t new_index = offset + index;
|
||||
assert(new_index < ptr_field->data.x_ptr.base_ptr->data.x_array.size);
|
||||
out_val->data.x_ptr.index = new_index;
|
||||
}
|
||||
} else if (array_type->id == TypeTableEntryIdArray) {
|
||||
out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_array.fields[index];
|
||||
out_val->data.x_ptr.base_ptr = &array_ptr->static_value;
|
||||
out_val->data.x_ptr.index = index;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -3790,9 +3819,9 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
|
||||
return type_entry;
|
||||
} else if (type_entry->id == TypeTableEntryIdPointer) {
|
||||
TypeTableEntry *child_type = type_entry->data.pointer.child_type;
|
||||
if (ptr->static_value.ok) {
|
||||
ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];
|
||||
if (pointee->ok) {
|
||||
if (ptr->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *pointee = const_ptr_pointee(&ptr->static_value);
|
||||
if (pointee->special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base,
|
||||
pointee->depends_on_compile_var);
|
||||
*out_val = *pointee;
|
||||
@ -3823,18 +3852,20 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
|
||||
if (casted_value == ira->codegen->invalid_instruction)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (ptr->static_value.ok && casted_value->static_value.ok) {
|
||||
ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0];
|
||||
if (dest_val->ok) {
|
||||
if (ptr->static_value.special != ConstValSpecialRuntime &&
|
||||
casted_value->static_value.special != ConstValSpecialRuntime)
|
||||
{
|
||||
ConstExprValue *dest_val = const_ptr_pointee(&ptr->static_value);
|
||||
if (dest_val->special != ConstValSpecialRuntime) {
|
||||
*dest_val = casted_value->static_value;
|
||||
return ir_analyze_void(ira, &store_ptr_instruction->base);
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr->static_value.ok) {
|
||||
if (ptr->static_value.special != ConstValSpecialRuntime) {
|
||||
// This memory location is transforming from known at compile time to known at runtime.
|
||||
// We must emit our own var ptr instruction.
|
||||
ptr->static_value.ok = false;
|
||||
ptr->static_value.special = ConstValSpecialRuntime;
|
||||
IrInstruction *new_ptr_inst;
|
||||
if (ptr->id == IrInstructionIdVarPtr) {
|
||||
IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr;
|
||||
@ -3842,7 +3873,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
|
||||
new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var);
|
||||
assert(var->mem_slot_index != SIZE_MAX);
|
||||
ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
|
||||
mem_slot->ok = false;
|
||||
mem_slot->special = ConstValSpecialRuntime;
|
||||
} else if (ptr->id == IrInstructionIdFieldPtr) {
|
||||
zig_panic("TODO");
|
||||
} else if (ptr->id == IrInstructionIdElemPtr) {
|
||||
@ -4236,7 +4267,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
|
||||
|
||||
IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;
|
||||
IrInstruction *value = ret_inst->value;
|
||||
assert(value->static_value.ok);
|
||||
assert(value->static_value.special != ConstValSpecialRuntime);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@ -19,5 +19,6 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl
|
||||
IrInstruction *ir_exec_const_result(IrExecutable *exec);
|
||||
|
||||
bool ir_has_side_effects(IrInstruction *instruction);
|
||||
ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);
|
||||
|
||||
#endif
|
||||
|
||||
@ -23,13 +23,15 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
|
||||
|
||||
static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
zig_unreachable();
|
||||
case ConstValSpecialUndef:
|
||||
fprintf(irp->f, "undefined");
|
||||
return;
|
||||
case ConstValSpecialZeroes:
|
||||
fprintf(irp->f, "zeroes");
|
||||
return;
|
||||
case ConstValSpecialOther:
|
||||
case ConstValSpecialStatic:
|
||||
break;
|
||||
}
|
||||
switch (type_entry->id) {
|
||||
@ -70,7 +72,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
|
||||
}
|
||||
case TypeTableEntryIdPointer:
|
||||
fprintf(irp->f, "&");
|
||||
ir_print_const_value(irp, type_entry->data.pointer.child_type, const_val->data.x_ptr.ptr[0]);
|
||||
ir_print_const_value(irp, type_entry->data.pointer.child_type, const_ptr_pointee(const_val));
|
||||
break;
|
||||
case TypeTableEntryIdFn:
|
||||
{
|
||||
@ -91,7 +93,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
if (i != 0)
|
||||
fprintf(irp->f, ",");
|
||||
ConstExprValue *child_value = const_val->data.x_array.fields[i];
|
||||
ConstExprValue *child_value = &const_val->data.x_array.elements[i];
|
||||
TypeTableEntry *child_type = type_entry->data.array.child_type;
|
||||
ir_print_const_value(irp, child_type, child_value);
|
||||
}
|
||||
@ -126,7 +128,7 @@ static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
}
|
||||
|
||||
static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
if (instruction->static_value.ok) {
|
||||
if (instruction->static_value.special != ConstValSpecialRuntime) {
|
||||
ir_print_const_instruction(irp, instruction);
|
||||
} else {
|
||||
ir_print_var_instruction(irp, instruction);
|
||||
|
||||
@ -2763,7 +2763,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
|
||||
old_node->data.prefix_op_expr.primary_expr, next_node_index);
|
||||
break;
|
||||
case NodeTypeFnCallExpr:
|
||||
assert(!old_node->data.fn_call_expr.resolved_expr.has_global_const);
|
||||
clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr,
|
||||
old_node->data.fn_call_expr.fn_ref_expr, next_node_index);
|
||||
clone_subtree_list(&new_node->data.fn_call_expr.params,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user