mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-29 12:08:48 +03:00
Merge remote-tracking branch 'origin/master' into llvm7
This commit is contained in:
+905
-602
@@ -243,7 +243,7 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
|
||||
g->root_out_name = out_name;
|
||||
}
|
||||
|
||||
void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir) {
|
||||
void codegen_set_cache_dir(CodeGen *g, Buf cache_dir) {
|
||||
g->cache_dir = cache_dir;
|
||||
}
|
||||
|
||||
@@ -358,6 +358,10 @@ static void addLLVMArgAttr(LLVMValueRef fn_val, unsigned param_index, const char
|
||||
return addLLVMAttr(fn_val, param_index + 1, attr_name);
|
||||
}
|
||||
|
||||
static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const char *attr_name, uint64_t attr_val) {
|
||||
return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val);
|
||||
}
|
||||
|
||||
static bool is_symbol_available(CodeGen *g, Buf *name) {
|
||||
return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr;
|
||||
}
|
||||
@@ -430,23 +434,23 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
if (!g->have_err_ret_tracing) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) {
|
||||
return 0;
|
||||
}
|
||||
TypeTableEntry *fn_type = fn_table_entry->type_entry;
|
||||
ZigType *fn_type = fn_table_entry->type_entry;
|
||||
if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
|
||||
ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
|
||||
bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type);
|
||||
return first_arg_ret ? 1 : 0;
|
||||
}
|
||||
|
||||
static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
if (fn_table_entry->llvm_value)
|
||||
return fn_table_entry->llvm_value;
|
||||
|
||||
@@ -466,7 +470,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
}
|
||||
|
||||
bool external_linkage = linkage != GlobalLinkageIdInternal;
|
||||
if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall && external_linkage &&
|
||||
CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
|
||||
if (cc == CallingConventionStdcall && external_linkage &&
|
||||
g->zig_target.arch.arch == ZigLLVM_x86)
|
||||
{
|
||||
// prevent llvm name mangling
|
||||
@@ -474,7 +479,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
}
|
||||
|
||||
|
||||
TypeTableEntry *fn_type = fn_table_entry->type_entry;
|
||||
ZigType *fn_type = fn_table_entry->type_entry;
|
||||
LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;
|
||||
if (fn_table_entry->body_node == nullptr) {
|
||||
LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
|
||||
@@ -510,17 +515,17 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (fn_type->data.fn.fn_type_id.cc == CallingConventionNaked) {
|
||||
if (cc == CallingConventionNaked) {
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "naked");
|
||||
} else {
|
||||
LLVMSetFunctionCallConv(fn_table_entry->llvm_value, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc));
|
||||
}
|
||||
if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
|
||||
if (cc == CallingConventionAsync) {
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "optnone");
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "noinline");
|
||||
}
|
||||
|
||||
bool want_cold = fn_table_entry->is_cold || fn_type->data.fn.fn_type_id.cc == CallingConventionCold;
|
||||
bool want_cold = fn_table_entry->is_cold || cc == CallingConventionCold;
|
||||
if (want_cold) {
|
||||
ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);
|
||||
}
|
||||
@@ -532,8 +537,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true);
|
||||
}
|
||||
|
||||
TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
|
||||
if (return_type->id == TypeTableEntryIdUnreachable) {
|
||||
ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
|
||||
if (return_type->id == ZigTypeIdUnreachable) {
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn");
|
||||
}
|
||||
|
||||
@@ -572,41 +577,26 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
||||
// use the ABI alignment, which is fine.
|
||||
}
|
||||
|
||||
unsigned init_gen_i = 0;
|
||||
if (!type_has_bits(return_type)) {
|
||||
// nothing to do
|
||||
} else if (type_is_codegen_pointer(return_type)) {
|
||||
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
|
||||
} else if (handle_is_ptr(return_type) &&
|
||||
calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
|
||||
{
|
||||
} else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
|
||||
if (cc == CallingConventionC) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
|
||||
}
|
||||
init_gen_i = 1;
|
||||
}
|
||||
|
||||
|
||||
// set parameter attributes
|
||||
for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) {
|
||||
FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
|
||||
size_t gen_index = gen_info->gen_index;
|
||||
bool is_byval = gen_info->is_byval;
|
||||
|
||||
if (gen_index == SIZE_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i];
|
||||
|
||||
TypeTableEntry *param_type = gen_info->type;
|
||||
if (param_info->is_noalias) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "noalias");
|
||||
}
|
||||
if ((param_type->id == TypeTableEntryIdPointer && param_type->data.pointer.is_const) || is_byval) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "readonly");
|
||||
}
|
||||
if (param_type->id == TypeTableEntryIdPointer) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
|
||||
}
|
||||
}
|
||||
FnWalk fn_walk = {};
|
||||
fn_walk.id = FnWalkIdAttrs;
|
||||
fn_walk.data.attrs.fn = fn_table_entry;
|
||||
fn_walk.data.attrs.gen_i = init_gen_i;
|
||||
walk_function_params(g, fn_type, &fn_walk);
|
||||
|
||||
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
|
||||
if (err_ret_trace_arg_index != UINT32_MAX) {
|
||||
@@ -628,7 +618,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
|
||||
{
|
||||
assert(scope->parent);
|
||||
ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
|
||||
FnTableEntry *fn_table_entry = fn_scope->fn_entry;
|
||||
ZigFn *fn_table_entry = fn_scope->fn_entry;
|
||||
if (!fn_table_entry->proto_node)
|
||||
return get_di_scope(g, scope->parent);
|
||||
unsigned line_number = (unsigned)(fn_table_entry->proto_node->line == 0) ?
|
||||
@@ -678,6 +668,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
|
||||
case ScopeIdSuspend:
|
||||
case ScopeIdCompTime:
|
||||
case ScopeIdCoroPrelude:
|
||||
case ScopeIdRuntime:
|
||||
return get_di_scope(g, scope->parent);
|
||||
}
|
||||
zig_unreachable();
|
||||
@@ -687,12 +678,12 @@ static void clear_debug_source_node(CodeGen *g) {
|
||||
ZigLLVMClearCurrentDebugLocation(g->builder);
|
||||
}
|
||||
|
||||
static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
|
||||
static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *type_entry,
|
||||
const char *signed_name, const char *unsigned_name)
|
||||
{
|
||||
char fn_name[64];
|
||||
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name;
|
||||
sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, type_entry->data.integral.bit_count);
|
||||
|
||||
@@ -711,8 +702,8 @@ static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_
|
||||
return fn_val;
|
||||
}
|
||||
|
||||
static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry, AddSubMul add_sub_mul) {
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubMul add_sub_mul) {
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
|
||||
ZigLLVMFnKey key = {};
|
||||
key.id = ZigLLVMFnIdOverflowArithmetic;
|
||||
@@ -741,8 +732,8 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
|
||||
return fn_val;
|
||||
}
|
||||
|
||||
static LLVMValueRef get_float_fn(CodeGen *g, TypeTableEntry *type_entry, ZigLLVMFnId fn_id) {
|
||||
assert(type_entry->id == TypeTableEntryIdFloat);
|
||||
static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id) {
|
||||
assert(type_entry->id == ZigTypeIdFloat);
|
||||
|
||||
ZigLLVMFnKey key = {};
|
||||
key.id = fn_id;
|
||||
@@ -786,8 +777,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
|
||||
return instruction;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, TypeTableEntry *ptr_type) {
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
return gen_store_untyped(g, value, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);
|
||||
}
|
||||
|
||||
@@ -804,17 +795,17 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig
|
||||
return result;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type, const char *name) {
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
return gen_load_untyped(g, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile, name);
|
||||
}
|
||||
|
||||
static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type, TypeTableEntry *ptr_type) {
|
||||
static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {
|
||||
if (type_has_bits(type)) {
|
||||
if (handle_is_ptr(type)) {
|
||||
return ptr;
|
||||
} else {
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
return gen_load(g, ptr, ptr_type, "");
|
||||
}
|
||||
} else {
|
||||
@@ -917,9 +908,9 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
|
||||
assert(val->global_refs->llvm_global);
|
||||
}
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
ZigType *str_type = get_slice_type(g, u8_ptr_type);
|
||||
return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0));
|
||||
}
|
||||
|
||||
@@ -928,7 +919,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
|
||||
LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
|
||||
LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);
|
||||
if (stack_trace_arg == nullptr) {
|
||||
TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
|
||||
ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
|
||||
stack_trace_arg = LLVMConstNull(ptr_to_stack_trace_type->type_ref);
|
||||
}
|
||||
LLVMValueRef args[] = {
|
||||
@@ -1166,7 +1157,7 @@ static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
|
||||
if (g->return_address_fn_val)
|
||||
return g->return_address_fn_val;
|
||||
|
||||
TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
ZigType *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
|
||||
LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref,
|
||||
&g->builtin_types.entry_i32->type_ref, 1, false);
|
||||
@@ -1217,7 +1208,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
|
||||
size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
|
||||
LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, "");
|
||||
|
||||
TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
|
||||
ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
|
||||
size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, "");
|
||||
size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index;
|
||||
@@ -1317,7 +1308,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
|
||||
(unsigned)src_index_field_index, "");
|
||||
LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr,
|
||||
(unsigned)src_addresses_field_index, "");
|
||||
TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
|
||||
ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
|
||||
size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)ptr_field_index, "");
|
||||
size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index;
|
||||
@@ -1459,7 +1450,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
|
||||
LLVMSetUnnamedAddr(global_array, true);
|
||||
LLVMSetAlignment(global_array, u8_align_bytes);
|
||||
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef full_buf_ptr_indices[] = {
|
||||
LLVMConstNull(usize->type_ref),
|
||||
LLVMConstNull(usize->type_ref),
|
||||
@@ -1467,9 +1458,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
|
||||
LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_array, full_buf_ptr_indices, 2);
|
||||
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
ZigType *str_type = get_slice_type(g, u8_ptr_type);
|
||||
LLVMValueRef global_slice_fields[] = {
|
||||
full_buf_ptr,
|
||||
LLVMConstNull(usize->type_ref),
|
||||
@@ -1575,7 +1566,7 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc
|
||||
LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
|
||||
LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
|
||||
if (err_ret_trace_val == nullptr) {
|
||||
TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
|
||||
ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
|
||||
err_ret_trace_val = LLVMConstNull(ptr_to_stack_trace_type->type_ref);
|
||||
}
|
||||
LLVMValueRef args[] = {
|
||||
@@ -1621,24 +1612,24 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, TypeTableEntry *actual_type,
|
||||
TypeTableEntry *wanted_type, LLVMValueRef expr_val)
|
||||
static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
|
||||
ZigType *wanted_type, LLVMValueRef expr_val)
|
||||
{
|
||||
assert(actual_type->id == wanted_type->id);
|
||||
|
||||
uint64_t actual_bits;
|
||||
uint64_t wanted_bits;
|
||||
if (actual_type->id == TypeTableEntryIdFloat) {
|
||||
if (actual_type->id == ZigTypeIdFloat) {
|
||||
actual_bits = actual_type->data.floating.bit_count;
|
||||
wanted_bits = wanted_type->data.floating.bit_count;
|
||||
} else if (actual_type->id == TypeTableEntryIdInt) {
|
||||
} else if (actual_type->id == ZigTypeIdInt) {
|
||||
actual_bits = actual_type->data.integral.bit_count;
|
||||
wanted_bits = wanted_type->data.integral.bit_count;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
if (actual_bits >= wanted_bits && actual_type->id == TypeTableEntryIdInt &&
|
||||
if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt &&
|
||||
!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
|
||||
want_runtime_safety)
|
||||
{
|
||||
@@ -1658,9 +1649,9 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, T
|
||||
if (actual_bits == wanted_bits) {
|
||||
return expr_val;
|
||||
} else if (actual_bits < wanted_bits) {
|
||||
if (actual_type->id == TypeTableEntryIdFloat) {
|
||||
if (actual_type->id == ZigTypeIdFloat) {
|
||||
return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
} else if (actual_type->id == TypeTableEntryIdInt) {
|
||||
} else if (actual_type->id == ZigTypeIdInt) {
|
||||
if (actual_type->data.integral.is_signed) {
|
||||
return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
} else {
|
||||
@@ -1670,9 +1661,9 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, T
|
||||
zig_unreachable();
|
||||
}
|
||||
} else if (actual_bits > wanted_bits) {
|
||||
if (actual_type->id == TypeTableEntryIdFloat) {
|
||||
if (actual_type->id == ZigTypeIdFloat) {
|
||||
return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
} else if (actual_type->id == TypeTableEntryIdInt) {
|
||||
} else if (actual_type->id == ZigTypeIdInt) {
|
||||
LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
if (!want_runtime_safety) {
|
||||
return trunc_val;
|
||||
@@ -1701,7 +1692,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, T
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op,
|
||||
static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *type_entry, AddSubMul op,
|
||||
LLVMValueRef val1, LLVMValueRef val2)
|
||||
{
|
||||
LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
|
||||
@@ -1761,11 +1752,11 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type,
|
||||
static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *child_type = ptr_type->data.pointer.child_type;
|
||||
|
||||
if (!type_has_bits(child_type))
|
||||
return nullptr;
|
||||
@@ -1779,7 +1770,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry
|
||||
LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, value, ptr_u8, "");
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
|
||||
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref);
|
||||
uint64_t align_bytes = ptr_type->data.pointer.alignment;
|
||||
assert(size_bytes > 0);
|
||||
@@ -1819,7 +1810,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) {
|
||||
static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {
|
||||
assert(var->di_loc_var != nullptr);
|
||||
AstNode *source_node = var->decl_node;
|
||||
ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1,
|
||||
(unsigned)source_node->column + 1, get_di_scope(g, var->parent_scope));
|
||||
@@ -1838,9 +1830,9 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
|
||||
// values are rendered with a type other than the one we expect
|
||||
if (handle_is_ptr(instruction->value.type)) {
|
||||
render_const_val_global(g, &instruction->value, "");
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
|
||||
ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
|
||||
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, ptr_type->type_ref, "");
|
||||
} else if (instruction->value.type->id == TypeTableEntryIdPointer) {
|
||||
} else if (instruction->value.type->id == ZigTypeIdPointer) {
|
||||
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value, instruction->value.type->type_ref, "");
|
||||
} else {
|
||||
instruction->llvm_value = instruction->value.global_refs->llvm_value;
|
||||
@@ -1850,6 +1842,353 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
|
||||
return instruction->llvm_value;
|
||||
}
|
||||
|
||||
ATTRIBUTE_NORETURN
|
||||
static void report_errors_and_exit(CodeGen *g) {
|
||||
assert(g->errors.length != 0);
|
||||
for (size_t i = 0; i < g->errors.length; i += 1) {
|
||||
ErrorMsg *err = g->errors.at(i);
|
||||
print_err_msg(err, g->err_color);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void report_errors_and_maybe_exit(CodeGen *g) {
|
||||
if (g->errors.length != 0) {
|
||||
report_errors_and_exit(g);
|
||||
}
|
||||
}
|
||||
|
||||
ATTRIBUTE_NORETURN
|
||||
static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
|
||||
ErrorMsg *msg = add_node_error(g, source_node,
|
||||
buf_sprintf("TODO: support C ABI for more targets. https://github.com/ziglang/zig/issues/1481"));
|
||||
add_error_note(g, msg, source_node,
|
||||
buf_sprintf("pointers, integers, floats, bools, and enums work on all targets"));
|
||||
report_errors_and_exit(g);
|
||||
}
|
||||
|
||||
static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
|
||||
assert(alignment > 0);
|
||||
LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
|
||||
LLVMSetAlignment(result, alignment);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk, size_t src_i) {
|
||||
// Initialized from the type for some walks, but because of C var args,
|
||||
// initialized based on callsite instructions for that one.
|
||||
FnTypeParamInfo *param_info = nullptr;
|
||||
ZigType *ty;
|
||||
ZigType *dest_ty = nullptr;
|
||||
AstNode *source_node = nullptr;
|
||||
LLVMValueRef val;
|
||||
LLVMValueRef llvm_fn;
|
||||
unsigned di_arg_index;
|
||||
ZigVar *var;
|
||||
switch (fn_walk->id) {
|
||||
case FnWalkIdAttrs:
|
||||
if (src_i >= fn_type->data.fn.fn_type_id.param_count)
|
||||
return false;
|
||||
param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
|
||||
ty = param_info->type;
|
||||
source_node = fn_walk->data.attrs.fn->proto_node;
|
||||
llvm_fn = fn_walk->data.attrs.fn->llvm_value;
|
||||
break;
|
||||
case FnWalkIdCall: {
|
||||
if (src_i >= fn_walk->data.call.inst->arg_count)
|
||||
return false;
|
||||
IrInstruction *arg = fn_walk->data.call.inst->args[src_i];
|
||||
ty = arg->value.type;
|
||||
source_node = arg->source_node;
|
||||
val = ir_llvm_value(g, arg);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdTypes:
|
||||
if (src_i >= fn_type->data.fn.fn_type_id.param_count)
|
||||
return false;
|
||||
param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
|
||||
ty = param_info->type;
|
||||
break;
|
||||
case FnWalkIdVars:
|
||||
assert(src_i < fn_type->data.fn.fn_type_id.param_count);
|
||||
param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
|
||||
ty = param_info->type;
|
||||
var = fn_walk->data.vars.var;
|
||||
source_node = var->decl_node;
|
||||
llvm_fn = fn_walk->data.vars.llvm_fn;
|
||||
break;
|
||||
case FnWalkIdInits:
|
||||
if (src_i >= fn_type->data.fn.fn_type_id.param_count)
|
||||
return false;
|
||||
param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
|
||||
ty = param_info->type;
|
||||
var = fn_walk->data.inits.fn->variable_list.at(src_i);
|
||||
source_node = fn_walk->data.inits.fn->proto_node;
|
||||
llvm_fn = fn_walk->data.inits.llvm_fn;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
|
||||
ty->id == ZigTypeIdInt // TODO investigate if we need to change this
|
||||
) {
|
||||
switch (fn_walk->id) {
|
||||
case FnWalkIdAttrs: {
|
||||
ZigType *ptr_type = get_codegen_ptr_type(ty);
|
||||
if (ptr_type != nullptr) {
|
||||
if (ty->id != ZigTypeIdOptional) {
|
||||
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
|
||||
}
|
||||
if (ptr_type->data.pointer.is_const) {
|
||||
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "readonly");
|
||||
}
|
||||
if (param_info->is_noalias) {
|
||||
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "noalias");
|
||||
}
|
||||
}
|
||||
fn_walk->data.attrs.gen_i += 1;
|
||||
break;
|
||||
}
|
||||
case FnWalkIdCall:
|
||||
fn_walk->data.call.gen_param_values->append(val);
|
||||
break;
|
||||
case FnWalkIdTypes:
|
||||
fn_walk->data.types.gen_param_types->append(ty->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(ty->di_type);
|
||||
break;
|
||||
case FnWalkIdVars: {
|
||||
var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes);
|
||||
di_arg_index = fn_walk->data.vars.gen_i;
|
||||
fn_walk->data.vars.gen_i += 1;
|
||||
dest_ty = ty;
|
||||
goto var_ok;
|
||||
}
|
||||
case FnWalkIdInits:
|
||||
clear_debug_source_node(g);
|
||||
gen_store_untyped(g, LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i), var->value_ref, var->align_bytes, false);
|
||||
if (var->decl_node) {
|
||||
gen_var_debug_decl(g, var);
|
||||
}
|
||||
fn_walk->data.inits.gen_i += 1;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Arrays are just pointers
|
||||
if (ty->id == ZigTypeIdArray) {
|
||||
assert(handle_is_ptr(ty));
|
||||
switch (fn_walk->id) {
|
||||
case FnWalkIdAttrs:
|
||||
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
|
||||
addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
|
||||
fn_walk->data.attrs.gen_i += 1;
|
||||
break;
|
||||
case FnWalkIdCall:
|
||||
fn_walk->data.call.gen_param_values->append(val);
|
||||
break;
|
||||
case FnWalkIdTypes: {
|
||||
ZigType *gen_type = get_pointer_to_type(g, ty, true);
|
||||
fn_walk->data.types.gen_param_types->append(gen_type->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(gen_type->di_type);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdVars: {
|
||||
var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
|
||||
di_arg_index = fn_walk->data.vars.gen_i;
|
||||
dest_ty = get_pointer_to_type(g, ty, false);
|
||||
fn_walk->data.vars.gen_i += 1;
|
||||
goto var_ok;
|
||||
}
|
||||
case FnWalkIdInits:
|
||||
if (var->decl_node) {
|
||||
gen_var_debug_decl(g, var);
|
||||
}
|
||||
fn_walk->data.inits.gen_i += 1;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
|
||||
X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
|
||||
size_t ty_size = type_size(g, ty);
|
||||
if (abi_class == X64CABIClass_MEMORY) {
|
||||
assert(handle_is_ptr(ty));
|
||||
switch (fn_walk->id) {
|
||||
case FnWalkIdAttrs:
|
||||
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
|
||||
addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
|
||||
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
|
||||
fn_walk->data.attrs.gen_i += 1;
|
||||
break;
|
||||
case FnWalkIdCall:
|
||||
fn_walk->data.call.gen_param_values->append(val);
|
||||
break;
|
||||
case FnWalkIdTypes: {
|
||||
ZigType *gen_type = get_pointer_to_type(g, ty, true);
|
||||
fn_walk->data.types.gen_param_types->append(gen_type->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(gen_type->di_type);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdVars: {
|
||||
di_arg_index = fn_walk->data.vars.gen_i;
|
||||
var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
|
||||
dest_ty = get_pointer_to_type(g, ty, false);
|
||||
fn_walk->data.vars.gen_i += 1;
|
||||
goto var_ok;
|
||||
}
|
||||
case FnWalkIdInits:
|
||||
if (var->decl_node) {
|
||||
gen_var_debug_decl(g, var);
|
||||
}
|
||||
fn_walk->data.inits.gen_i += 1;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
} else if (abi_class == X64CABIClass_INTEGER) {
|
||||
switch (fn_walk->id) {
|
||||
case FnWalkIdAttrs:
|
||||
fn_walk->data.attrs.gen_i += 1;
|
||||
break;
|
||||
case FnWalkIdCall: {
|
||||
LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0);
|
||||
LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, val, ptr_to_int_type_ref, "");
|
||||
LLVMValueRef loaded = LLVMBuildLoad(g->builder, bitcasted, "");
|
||||
fn_walk->data.call.gen_param_values->append(loaded);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdTypes: {
|
||||
ZigType *gen_type = get_int_type(g, false, ty_size * 8);
|
||||
fn_walk->data.types.gen_param_types->append(gen_type->type_ref);
|
||||
fn_walk->data.types.param_di_types->append(gen_type->di_type);
|
||||
break;
|
||||
}
|
||||
case FnWalkIdVars: {
|
||||
di_arg_index = fn_walk->data.vars.gen_i;
|
||||
var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes);
|
||||
fn_walk->data.vars.gen_i += 1;
|
||||
dest_ty = ty;
|
||||
goto var_ok;
|
||||
}
|
||||
case FnWalkIdInits: {
|
||||
clear_debug_source_node(g);
|
||||
LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i);
|
||||
LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0);
|
||||
LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, "");
|
||||
gen_store_untyped(g, arg, bitcasted, var->align_bytes, false);
|
||||
if (var->decl_node) {
|
||||
gen_var_debug_decl(g, var);
|
||||
}
|
||||
fn_walk->data.inits.gen_i += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (source_node != nullptr) {
|
||||
give_up_with_c_abi_error(g, source_node);
|
||||
}
|
||||
// otherwise allow codegen code to report a compile error
|
||||
return false;
|
||||
|
||||
var_ok:
|
||||
if (dest_ty != nullptr && var->decl_node) {
|
||||
// arg index + 1 because the 0 index is return value
|
||||
var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
|
||||
buf_ptr(&var->name), fn_walk->data.vars.import->di_file,
|
||||
(unsigned)(var->decl_node->line + 1),
|
||||
dest_ty->di_type, !g->strip_debug_symbols, 0, di_arg_index + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
|
||||
CallingConvention cc = fn_type->data.fn.fn_type_id.cc;
|
||||
if (cc == CallingConventionC) {
|
||||
size_t src_i = 0;
|
||||
for (;;) {
|
||||
if (!iter_function_params_c_abi(g, fn_type, fn_walk, src_i))
|
||||
break;
|
||||
src_i += 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (fn_walk->id == FnWalkIdCall) {
|
||||
IrInstructionCall *instruction = fn_walk->data.call.inst;
|
||||
bool is_var_args = fn_walk->data.call.is_var_args;
|
||||
for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
|
||||
IrInstruction *param_instruction = instruction->args[call_i];
|
||||
ZigType *param_type = param_instruction->value.type;
|
||||
if (is_var_args || type_has_bits(param_type)) {
|
||||
LLVMValueRef param_value = ir_llvm_value(g, param_instruction);
|
||||
assert(param_value);
|
||||
fn_walk->data.call.gen_param_values->append(param_value);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
size_t next_var_i = 0;
|
||||
for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) {
|
||||
FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
|
||||
size_t gen_index = gen_info->gen_index;
|
||||
|
||||
if (gen_index == SIZE_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (fn_walk->id) {
|
||||
case FnWalkIdAttrs: {
|
||||
LLVMValueRef llvm_fn = fn_walk->data.attrs.fn->llvm_value;
|
||||
bool is_byval = gen_info->is_byval;
|
||||
FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i];
|
||||
|
||||
ZigType *param_type = gen_info->type;
|
||||
if (param_info->is_noalias) {
|
||||
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "noalias");
|
||||
}
|
||||
if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
|
||||
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
|
||||
}
|
||||
if (param_type->id == ZigTypeIdPointer) {
|
||||
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FnWalkIdInits: {
|
||||
ZigFn *fn_table_entry = fn_walk->data.inits.fn;
|
||||
LLVMValueRef llvm_fn = fn_table_entry->llvm_value;
|
||||
ZigVar *variable = fn_table_entry->variable_list.at(next_var_i);
|
||||
assert(variable->src_arg_index != SIZE_MAX);
|
||||
next_var_i += 1;
|
||||
|
||||
assert(variable);
|
||||
assert(variable->value_ref);
|
||||
|
||||
if (!handle_is_ptr(variable->value->type)) {
|
||||
clear_debug_source_node(g);
|
||||
gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,
|
||||
variable->align_bytes, false);
|
||||
}
|
||||
|
||||
if (variable->decl_node) {
|
||||
gen_var_debug_decl(g, variable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FnWalkIdCall:
|
||||
// handled before for loop
|
||||
zig_unreachable();
|
||||
case FnWalkIdTypes:
|
||||
// Not called for non-c-abi
|
||||
zig_unreachable();
|
||||
case FnWalkIdVars:
|
||||
// iter_function_params_c_abi is called directly for this one
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionSaveErrRetAddr *save_err_ret_addr_instruction)
|
||||
{
|
||||
@@ -1866,24 +2205,22 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
|
||||
|
||||
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
|
||||
LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
|
||||
TypeTableEntry *return_type = return_instruction->value->value.type;
|
||||
ZigType *return_type = return_instruction->value->value.type;
|
||||
|
||||
if (handle_is_ptr(return_type)) {
|
||||
if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) {
|
||||
assert(g->cur_ret_ptr);
|
||||
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
|
||||
LLVMBuildRetVoid(g->builder);
|
||||
} else {
|
||||
LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
|
||||
LLVMBuildRet(g->builder, by_val_value);
|
||||
}
|
||||
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
|
||||
assert(g->cur_ret_ptr);
|
||||
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
|
||||
LLVMBuildRetVoid(g->builder);
|
||||
} else if (handle_is_ptr(return_type)) {
|
||||
LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
|
||||
LLVMBuildRet(g->builder, by_val_value);
|
||||
} else {
|
||||
LLVMBuildRet(g->builder, value);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
|
||||
static LLVMValueRef gen_overflow_shl_op(CodeGen *g, ZigType *type_entry,
|
||||
LLVMValueRef val1, LLVMValueRef val2)
|
||||
{
|
||||
// for unsigned left shifting, we do the lossy shift, then logically shift
|
||||
@@ -1891,7 +2228,7 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
|
||||
// if the values don't match, we have an overflow
|
||||
// for signed left shifting we do the same except arithmetic shift right
|
||||
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
|
||||
LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
|
||||
LLVMValueRef orig_val;
|
||||
@@ -1913,10 +2250,10 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
|
||||
return result;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_overflow_shr_op(CodeGen *g, TypeTableEntry *type_entry,
|
||||
static LLVMValueRef gen_overflow_shr_op(CodeGen *g, ZigType *type_entry,
|
||||
LLVMValueRef val1, LLVMValueRef val2)
|
||||
{
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
|
||||
LLVMValueRef result;
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
@@ -1938,16 +2275,16 @@ static LLVMValueRef gen_overflow_shr_op(CodeGen *g, TypeTableEntry *type_entry,
|
||||
return result;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_floor(CodeGen *g, LLVMValueRef val, TypeTableEntry *type_entry) {
|
||||
if (type_entry->id == TypeTableEntryIdInt)
|
||||
static LLVMValueRef gen_floor(CodeGen *g, LLVMValueRef val, ZigType *type_entry) {
|
||||
if (type_entry->id == ZigTypeIdInt)
|
||||
return val;
|
||||
|
||||
LLVMValueRef floor_fn = get_float_fn(g, type_entry, ZigLLVMFnIdFloor);
|
||||
return LLVMBuildCall(g->builder, floor_fn, &val, 1, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_ceil(CodeGen *g, LLVMValueRef val, TypeTableEntry *type_entry) {
|
||||
if (type_entry->id == TypeTableEntryIdInt)
|
||||
static LLVMValueRef gen_ceil(CodeGen *g, LLVMValueRef val, ZigType *type_entry) {
|
||||
if (type_entry->id == ZigTypeIdInt)
|
||||
return val;
|
||||
|
||||
LLVMValueRef ceil_fn = get_float_fn(g, type_entry, ZigLLVMFnIdCeil);
|
||||
@@ -1980,16 +2317,16 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
|
||||
|
||||
static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast_math,
|
||||
LLVMValueRef val1, LLVMValueRef val2,
|
||||
TypeTableEntry *type_entry, DivKind div_kind)
|
||||
ZigType *type_entry, DivKind div_kind)
|
||||
{
|
||||
ZigLLVMSetFastMath(g->builder, want_fast_math);
|
||||
|
||||
LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
|
||||
if (want_runtime_safety && (want_fast_math || type_entry->id != TypeTableEntryIdFloat)) {
|
||||
if (want_runtime_safety && (want_fast_math || type_entry->id != ZigTypeIdFloat)) {
|
||||
LLVMValueRef is_zero_bit;
|
||||
if (type_entry->id == TypeTableEntryIdInt) {
|
||||
if (type_entry->id == ZigTypeIdInt) {
|
||||
is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
} else if (type_entry->id == ZigTypeIdFloat) {
|
||||
is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
|
||||
} else {
|
||||
zig_unreachable();
|
||||
@@ -2003,7 +2340,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block);
|
||||
|
||||
if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) {
|
||||
if (type_entry->id == ZigTypeIdInt && type_entry->data.integral.is_signed) {
|
||||
LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true);
|
||||
BigInt int_min_bi = {0};
|
||||
eval_min_max_value_int(g, type_entry, &int_min_bi, false);
|
||||
@@ -2022,7 +2359,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
|
||||
}
|
||||
}
|
||||
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == ZigTypeIdFloat) {
|
||||
LLVMValueRef result = LLVMBuildFDiv(g->builder, val1, val2, "");
|
||||
switch (div_kind) {
|
||||
case DivKindFloat:
|
||||
@@ -2073,7 +2410,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
|
||||
switch (div_kind) {
|
||||
case DivKindFloat:
|
||||
@@ -2139,17 +2476,17 @@ enum RemKind {
|
||||
|
||||
static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast_math,
|
||||
LLVMValueRef val1, LLVMValueRef val2,
|
||||
TypeTableEntry *type_entry, RemKind rem_kind)
|
||||
ZigType *type_entry, RemKind rem_kind)
|
||||
{
|
||||
ZigLLVMSetFastMath(g->builder, want_fast_math);
|
||||
|
||||
LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
|
||||
if (want_runtime_safety) {
|
||||
LLVMValueRef is_zero_bit;
|
||||
if (type_entry->id == TypeTableEntryIdInt) {
|
||||
if (type_entry->id == ZigTypeIdInt) {
|
||||
LLVMIntPredicate pred = type_entry->data.integral.is_signed ? LLVMIntSLE : LLVMIntEQ;
|
||||
is_zero_bit = LLVMBuildICmp(g->builder, pred, val2, zero, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
} else if (type_entry->id == ZigTypeIdFloat) {
|
||||
is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
|
||||
} else {
|
||||
zig_unreachable();
|
||||
@@ -2164,7 +2501,7 @@ static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast
|
||||
LLVMPositionBuilderAtEnd(g->builder, rem_zero_ok_block);
|
||||
}
|
||||
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == ZigTypeIdFloat) {
|
||||
if (rem_kind == RemKindRem) {
|
||||
return LLVMBuildFRem(g->builder, val1, val2, "");
|
||||
} else {
|
||||
@@ -2175,7 +2512,7 @@ static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast
|
||||
return LLVMBuildSelect(g->builder, ltz, c, a, "");
|
||||
}
|
||||
} else {
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
if (rem_kind == RemKindRem) {
|
||||
return LLVMBuildSRem(g->builder, val1, val2, "");
|
||||
@@ -2203,12 +2540,12 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
assert(op1->value.type == op2->value.type || op_id == IrBinOpBitShiftLeftLossy ||
|
||||
op_id == IrBinOpBitShiftLeftExact || op_id == IrBinOpBitShiftRightLossy ||
|
||||
op_id == IrBinOpBitShiftRightExact ||
|
||||
(op1->value.type->id == TypeTableEntryIdErrorSet && op2->value.type->id == TypeTableEntryIdErrorSet) ||
|
||||
(op1->value.type->id == TypeTableEntryIdPointer &&
|
||||
(op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
|
||||
(op1->value.type->id == ZigTypeIdPointer &&
|
||||
(op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
|
||||
op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
|
||||
);
|
||||
TypeTableEntry *type_entry = op1->value.type;
|
||||
ZigType *type_entry = op1->value.type;
|
||||
|
||||
bool want_runtime_safety = bin_op_instruction->safety_check_on &&
|
||||
ir_want_runtime_safety(g, &bin_op_instruction->base);
|
||||
@@ -2234,16 +2571,16 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
case IrBinOpCmpGreaterThan:
|
||||
case IrBinOpCmpLessOrEq:
|
||||
case IrBinOpCmpGreaterOrEq:
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == ZigTypeIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
|
||||
return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == ZigTypeIdInt) {
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdEnum ||
|
||||
type_entry->id == TypeTableEntryIdErrorSet ||
|
||||
type_entry->id == TypeTableEntryIdBool ||
|
||||
} else if (type_entry->id == ZigTypeIdEnum ||
|
||||
type_entry->id == ZigTypeIdErrorSet ||
|
||||
type_entry->id == ZigTypeIdBool ||
|
||||
get_codegen_ptr_type(type_entry) != nullptr)
|
||||
{
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
|
||||
@@ -2253,14 +2590,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpAdd:
|
||||
case IrBinOpAddWrap:
|
||||
if (type_entry->id == TypeTableEntryIdPointer) {
|
||||
if (type_entry->id == ZigTypeIdPointer) {
|
||||
assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
|
||||
// TODO runtime safety
|
||||
return LLVMBuildInBoundsGEP(g->builder, op1_value, &op2_value, 1, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
} else if (type_entry->id == ZigTypeIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == ZigTypeIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpAddWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
|
||||
@@ -2283,7 +2620,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
case IrBinOpBitShiftLeftLossy:
|
||||
case IrBinOpBitShiftLeftExact:
|
||||
{
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
|
||||
type_entry, op2_value);
|
||||
bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
|
||||
@@ -2300,7 +2637,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
case IrBinOpBitShiftRightLossy:
|
||||
case IrBinOpBitShiftRightExact:
|
||||
{
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == ZigTypeIdInt);
|
||||
LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
|
||||
type_entry, op2_value);
|
||||
bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
|
||||
@@ -2320,15 +2657,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpSub:
|
||||
case IrBinOpSubWrap:
|
||||
if (type_entry->id == TypeTableEntryIdPointer) {
|
||||
if (type_entry->id == ZigTypeIdPointer) {
|
||||
assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
|
||||
// TODO runtime safety
|
||||
LLVMValueRef subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
|
||||
return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
} else if (type_entry->id == ZigTypeIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == ZigTypeIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpSubWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildSub(g->builder, op1_value, op2_value, "");
|
||||
@@ -2344,10 +2681,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpMult:
|
||||
case IrBinOpMultWrap:
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == ZigTypeIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == ZigTypeIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpMultWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildMul(g->builder, op1_value, op2_value, "");
|
||||
@@ -2383,8 +2720,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void add_error_range_check(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *int_type, LLVMValueRef target_val) {
|
||||
assert(err_set_type->id == TypeTableEntryIdErrorSet);
|
||||
static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *int_type, LLVMValueRef target_val) {
|
||||
assert(err_set_type->id == ZigTypeIdErrorSet);
|
||||
|
||||
if (type_is_global_error_set(err_set_type)) {
|
||||
LLVMValueRef zero = LLVMConstNull(int_type->type_ref);
|
||||
@@ -2434,8 +2771,8 @@ static void add_error_range_check(CodeGen *g, TypeTableEntry *err_set_type, Type
|
||||
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionCast *cast_instruction)
|
||||
{
|
||||
TypeTableEntry *actual_type = cast_instruction->value->value.type;
|
||||
TypeTableEntry *wanted_type = cast_instruction->base.value.type;
|
||||
ZigType *actual_type = cast_instruction->value->value.type;
|
||||
ZigType *wanted_type = cast_instruction->base.value.type;
|
||||
LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
|
||||
assert(expr_val);
|
||||
|
||||
@@ -2448,15 +2785,15 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
case CastOpResizeSlice:
|
||||
{
|
||||
assert(cast_instruction->tmp_ptr);
|
||||
assert(wanted_type->id == TypeTableEntryIdStruct);
|
||||
assert(wanted_type->id == ZigTypeIdStruct);
|
||||
assert(wanted_type->data.structure.is_slice);
|
||||
assert(actual_type->id == TypeTableEntryIdStruct);
|
||||
assert(actual_type->id == ZigTypeIdStruct);
|
||||
assert(actual_type->data.structure.is_slice);
|
||||
|
||||
TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
|
||||
TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type;
|
||||
TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
|
||||
TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
|
||||
ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
|
||||
ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type;
|
||||
ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
|
||||
ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
|
||||
|
||||
|
||||
size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
@@ -2511,12 +2848,12 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
case CastOpBytesToSlice:
|
||||
{
|
||||
assert(cast_instruction->tmp_ptr);
|
||||
assert(wanted_type->id == TypeTableEntryIdStruct);
|
||||
assert(wanted_type->id == ZigTypeIdStruct);
|
||||
assert(wanted_type->data.structure.is_slice);
|
||||
assert(actual_type->id == TypeTableEntryIdArray);
|
||||
assert(actual_type->id == ZigTypeIdArray);
|
||||
|
||||
TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
|
||||
ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
|
||||
|
||||
|
||||
size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
|
||||
@@ -2535,14 +2872,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
return cast_instruction->tmp_ptr;
|
||||
}
|
||||
case CastOpIntToFloat:
|
||||
assert(actual_type->id == TypeTableEntryIdInt);
|
||||
assert(actual_type->id == ZigTypeIdInt);
|
||||
if (actual_type->data.integral.is_signed) {
|
||||
return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
} else {
|
||||
return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
}
|
||||
case CastOpFloatToInt: {
|
||||
assert(wanted_type->id == TypeTableEntryIdInt);
|
||||
assert(wanted_type->id == ZigTypeIdInt);
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &cast_instruction->base));
|
||||
|
||||
bool want_safety = ir_want_runtime_safety(g, &cast_instruction->base);
|
||||
@@ -2577,8 +2914,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
return result;
|
||||
}
|
||||
case CastOpBoolToInt:
|
||||
assert(wanted_type->id == TypeTableEntryIdInt);
|
||||
assert(actual_type->id == TypeTableEntryIdBool);
|
||||
assert(wanted_type->id == ZigTypeIdInt);
|
||||
assert(actual_type->id == ZigTypeIdBool);
|
||||
return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
case CastOpErrSet:
|
||||
if (ir_want_runtime_safety(g, &cast_instruction->base)) {
|
||||
@@ -2589,9 +2926,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
case CastOpPtrOfArrayToSlice: {
|
||||
assert(cast_instruction->tmp_ptr);
|
||||
assert(actual_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *array_type = actual_type->data.pointer.child_type;
|
||||
assert(array_type->id == TypeTableEntryIdArray);
|
||||
assert(actual_type->id == ZigTypeIdPointer);
|
||||
ZigType *array_type = actual_type->data.pointer.child_type;
|
||||
assert(array_type->id == ZigTypeIdArray);
|
||||
|
||||
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
|
||||
slice_ptr_index, "");
|
||||
@@ -2617,7 +2954,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionPtrCast *instruction)
|
||||
{
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
if (!type_has_bits(wanted_type)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -2628,7 +2965,7 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
|
||||
static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionBitCast *instruction)
|
||||
{
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
return LLVMBuildBitCast(g->builder, value, wanted_type->type_ref, "");
|
||||
}
|
||||
@@ -2636,11 +2973,11 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
|
||||
static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionWidenOrShorten *instruction)
|
||||
{
|
||||
TypeTableEntry *actual_type = instruction->target->value.type;
|
||||
ZigType *actual_type = instruction->target->value.type;
|
||||
// TODO instead of this logic, use the Noop instruction to change the type from
|
||||
// enum_tag to the underlying int type
|
||||
TypeTableEntry *int_type;
|
||||
if (actual_type->id == TypeTableEntryIdEnum) {
|
||||
ZigType *int_type;
|
||||
if (actual_type->id == ZigTypeIdEnum) {
|
||||
int_type = actual_type->data.enumeration.tag_int_type;
|
||||
} else {
|
||||
int_type = actual_type;
|
||||
@@ -2651,21 +2988,21 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, IrInstructionPtrToInt *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == TypeTableEntryIdEnum);
|
||||
TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == ZigTypeIdEnum);
|
||||
ZigType *tag_int_type = wanted_type->data.enumeration.tag_int_type;
|
||||
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
|
||||
@@ -2690,11 +3027,11 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == TypeTableEntryIdErrorSet);
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == ZigTypeIdErrorSet);
|
||||
|
||||
TypeTableEntry *actual_type = instruction->target->value.type;
|
||||
assert(actual_type->id == TypeTableEntryIdInt);
|
||||
ZigType *actual_type = instruction->target->value.type;
|
||||
assert(actual_type->id == ZigTypeIdInt);
|
||||
assert(!actual_type->data.integral.is_signed);
|
||||
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
@@ -2707,17 +3044,17 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, IrInstructionErrToInt *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == TypeTableEntryIdInt);
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
assert(wanted_type->id == ZigTypeIdInt);
|
||||
assert(!wanted_type->data.integral.is_signed);
|
||||
|
||||
TypeTableEntry *actual_type = instruction->target->value.type;
|
||||
ZigType *actual_type = instruction->target->value.type;
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
|
||||
if (actual_type->id == TypeTableEntryIdErrorSet) {
|
||||
if (actual_type->id == ZigTypeIdErrorSet) {
|
||||
return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
|
||||
g->err_tag_type, wanted_type, target_val);
|
||||
} else if (actual_type->id == TypeTableEntryIdErrorUnion) {
|
||||
} else if (actual_type->id == ZigTypeIdErrorUnion) {
|
||||
// this should have been a compile time constant
|
||||
assert(type_has_bits(actual_type->data.error_union.err_set_type));
|
||||
|
||||
@@ -2761,7 +3098,7 @@ static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstruc
|
||||
static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {
|
||||
IrUnOp op_id = un_op_instruction->op_id;
|
||||
LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value);
|
||||
TypeTableEntry *expr_type = un_op_instruction->value->value.type;
|
||||
ZigType *expr_type = un_op_instruction->value->value.type;
|
||||
|
||||
switch (op_id) {
|
||||
case IrUnOpInvalid:
|
||||
@@ -2771,10 +3108,10 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
|
||||
case IrUnOpNegation:
|
||||
case IrUnOpNegationWrap:
|
||||
{
|
||||
if (expr_type->id == TypeTableEntryIdFloat) {
|
||||
if (expr_type->id == ZigTypeIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base));
|
||||
return LLVMBuildFNeg(g->builder, expr, "");
|
||||
} else if (expr_type->id == TypeTableEntryIdInt) {
|
||||
} else if (expr_type->id == ZigTypeIdInt) {
|
||||
if (op_id == IrUnOpNegationWrap) {
|
||||
return LLVMBuildNeg(g->builder, expr, "");
|
||||
} else if (ir_want_runtime_safety(g, &un_op_instruction->base)) {
|
||||
@@ -2805,7 +3142,7 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
|
||||
static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionDeclVar *decl_var_instruction)
|
||||
{
|
||||
VariableTableEntry *var = decl_var_instruction->var;
|
||||
ZigVar *var = decl_var_instruction->var;
|
||||
|
||||
if (!type_has_bits(var->value->type))
|
||||
return nullptr;
|
||||
@@ -2823,13 +3160,13 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
|
||||
if (have_init_expr) {
|
||||
assert(var->value->type == init_value->value.type);
|
||||
TypeTableEntry *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
|
||||
ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
|
||||
PtrLenSingle, var->align_bytes, 0, 0);
|
||||
gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value));
|
||||
} else {
|
||||
bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
|
||||
if (want_safe) {
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
|
||||
assert(size_bytes > 0);
|
||||
|
||||
@@ -2849,13 +3186,13 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {
|
||||
TypeTableEntry *child_type = instruction->base.value.type;
|
||||
ZigType *child_type = instruction->base.value.type;
|
||||
if (!type_has_bits(child_type))
|
||||
return nullptr;
|
||||
|
||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
||||
TypeTableEntry *ptr_type = instruction->ptr->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
ZigType *ptr_type = instruction->ptr->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
|
||||
uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
|
||||
if (unaligned_bit_count == 0)
|
||||
@@ -2880,8 +3217,8 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
|
||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
|
||||
assert(instruction->ptr->value.type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *ptr_type = instruction->ptr->value.type;
|
||||
assert(instruction->ptr->value.type->id == ZigTypeIdPointer);
|
||||
ZigType *ptr_type = instruction->ptr->value.type;
|
||||
|
||||
gen_assign_raw(g, ptr, ptr_type, value);
|
||||
|
||||
@@ -2889,7 +3226,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
|
||||
VariableTableEntry *var = instruction->var;
|
||||
ZigVar *var = instruction->var;
|
||||
if (type_has_bits(var->value->type)) {
|
||||
assert(var->value_ref);
|
||||
return var->value_ref;
|
||||
@@ -2900,9 +3237,9 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
|
||||
|
||||
static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {
|
||||
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);
|
||||
TypeTableEntry *array_ptr_type = instruction->array_ptr->value.type;
|
||||
assert(array_ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type;
|
||||
ZigType *array_ptr_type = instruction->array_ptr->value.type;
|
||||
assert(array_ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *array_type = array_ptr_type->data.pointer.child_type;
|
||||
LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
|
||||
LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);
|
||||
assert(subscript_value);
|
||||
@@ -2912,11 +3249,11 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
|
||||
bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on;
|
||||
|
||||
if (array_type->id == TypeTableEntryIdArray ||
|
||||
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
|
||||
if (array_type->id == ZigTypeIdArray ||
|
||||
(array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
|
||||
{
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
assert(array_type->data.pointer.child_type->id == TypeTableEntryIdArray);
|
||||
if (array_type->id == ZigTypeIdPointer) {
|
||||
assert(array_type->data.pointer.child_type->id == ZigTypeIdArray);
|
||||
array_type = array_type->data.pointer.child_type;
|
||||
}
|
||||
if (safety_check_on) {
|
||||
@@ -2927,8 +3264,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
if (array_ptr_type->data.pointer.unaligned_bit_count != 0) {
|
||||
return array_ptr_ptr;
|
||||
}
|
||||
TypeTableEntry *child_type = array_type->data.array.child_type;
|
||||
if (child_type->id == TypeTableEntryIdStruct &&
|
||||
ZigType *child_type = array_type->data.array.child_type;
|
||||
if (child_type->id == ZigTypeIdStruct &&
|
||||
child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
{
|
||||
size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
|
||||
@@ -2951,13 +3288,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
subscript_value
|
||||
};
|
||||
return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
} else if (array_type->id == ZigTypeIdPointer) {
|
||||
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
|
||||
LLVMValueRef indices[] = {
|
||||
subscript_value
|
||||
};
|
||||
return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
|
||||
} else if (array_type->id == TypeTableEntryIdStruct) {
|
||||
} else if (array_type->id == ZigTypeIdStruct) {
|
||||
assert(array_type->data.structure.is_slice);
|
||||
if (!type_has_bits(instruction->base.value.type)) {
|
||||
if (safety_check_on) {
|
||||
@@ -2990,8 +3327,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
|
||||
static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) {
|
||||
return g->have_err_ret_tracing &&
|
||||
(fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
|
||||
fn_type_id->return_type->id == TypeTableEntryIdErrorSet ||
|
||||
(fn_type_id->return_type->id == ZigTypeIdErrorUnion ||
|
||||
fn_type_id->return_type->id == ZigTypeIdErrorSet ||
|
||||
fn_type_id->cc == CallingConventionAsync);
|
||||
}
|
||||
|
||||
@@ -3047,7 +3384,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
|
||||
|
||||
static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
|
||||
LLVMValueRef fn_val;
|
||||
TypeTableEntry *fn_type;
|
||||
ZigType *fn_type;
|
||||
if (instruction->fn_entry) {
|
||||
fn_val = fn_llvm_value(g, instruction->fn_entry);
|
||||
fn_type = instruction->fn_entry->type_entry;
|
||||
@@ -3059,43 +3396,33 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
||||
|
||||
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
|
||||
|
||||
TypeTableEntry *src_return_type = fn_type_id->return_type;
|
||||
ZigType *src_return_type = fn_type_id->return_type;
|
||||
bool ret_has_bits = type_has_bits(src_return_type);
|
||||
|
||||
bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&
|
||||
calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc);
|
||||
CallingConvention cc = fn_type->data.fn.fn_type_id.cc;
|
||||
|
||||
bool first_arg_ret = ret_has_bits && want_first_arg_sret(g, fn_type_id);
|
||||
bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
|
||||
// +2 for the async args
|
||||
size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2;
|
||||
bool is_var_args = fn_type_id->is_var_args;
|
||||
LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
|
||||
size_t gen_param_index = 0;
|
||||
ZigList<LLVMValueRef> gen_param_values = {};
|
||||
if (first_arg_ret) {
|
||||
gen_param_values[gen_param_index] = instruction->tmp_ptr;
|
||||
gen_param_index += 1;
|
||||
gen_param_values.append(instruction->tmp_ptr);
|
||||
}
|
||||
if (prefix_arg_err_ret_stack) {
|
||||
gen_param_values[gen_param_index] = get_cur_err_ret_trace_val(g, instruction->base.scope);
|
||||
gen_param_index += 1;
|
||||
gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
|
||||
}
|
||||
if (instruction->is_async) {
|
||||
gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->async_allocator);
|
||||
gen_param_index += 1;
|
||||
gen_param_values.append(ir_llvm_value(g, instruction->async_allocator));
|
||||
|
||||
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
|
||||
gen_param_values[gen_param_index] = err_val_ptr;
|
||||
gen_param_index += 1;
|
||||
}
|
||||
for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
|
||||
IrInstruction *param_instruction = instruction->args[call_i];
|
||||
TypeTableEntry *param_type = param_instruction->value.type;
|
||||
if (is_var_args || type_has_bits(param_type)) {
|
||||
LLVMValueRef param_value = ir_llvm_value(g, param_instruction);
|
||||
assert(param_value);
|
||||
gen_param_values[gen_param_index] = param_value;
|
||||
gen_param_index += 1;
|
||||
}
|
||||
gen_param_values.append(err_val_ptr);
|
||||
}
|
||||
FnWalk fn_walk = {};
|
||||
fn_walk.id = FnWalkIdCall;
|
||||
fn_walk.data.call.inst = instruction;
|
||||
fn_walk.data.call.is_var_args = is_var_args;
|
||||
fn_walk.data.call.gen_param_values = &gen_param_values;
|
||||
walk_function_params(g, fn_type, &fn_walk);
|
||||
|
||||
ZigLLVM_FnInline fn_inline;
|
||||
switch (instruction->fn_inline) {
|
||||
@@ -3110,12 +3437,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
||||
break;
|
||||
}
|
||||
|
||||
LLVMCallConv llvm_cc = get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc);
|
||||
LLVMCallConv llvm_cc = get_llvm_cc(g, cc);
|
||||
LLVMValueRef result;
|
||||
|
||||
if (instruction->new_stack == nullptr) {
|
||||
result = ZigLLVMBuildCall(g->builder, fn_val,
|
||||
gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, "");
|
||||
gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");
|
||||
} else {
|
||||
LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);
|
||||
LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);
|
||||
@@ -3124,7 +3451,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
||||
LLVMValueRef old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, "");
|
||||
gen_set_stack_pointer(g, new_stack_addr);
|
||||
result = ZigLLVMBuildCall(g->builder, fn_val,
|
||||
gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, "");
|
||||
gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");
|
||||
LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, "");
|
||||
}
|
||||
|
||||
@@ -3135,7 +3462,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
||||
return instruction->tmp_ptr;
|
||||
}
|
||||
|
||||
if (src_return_type->id == TypeTableEntryIdUnreachable) {
|
||||
if (src_return_type->id == ZigTypeIdUnreachable) {
|
||||
return LLVMBuildUnreachable(g->builder);
|
||||
} else if (!ret_has_bits) {
|
||||
return nullptr;
|
||||
@@ -3155,14 +3482,14 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
|
||||
IrInstructionStructFieldPtr *instruction)
|
||||
{
|
||||
LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
|
||||
// not necessarily a pointer. could be TypeTableEntryIdStruct
|
||||
TypeTableEntry *struct_ptr_type = instruction->struct_ptr->value.type;
|
||||
// not necessarily a pointer. could be ZigTypeIdStruct
|
||||
ZigType *struct_ptr_type = instruction->struct_ptr->value.type;
|
||||
TypeStructField *field = instruction->field;
|
||||
|
||||
if (!type_has_bits(field->type_entry))
|
||||
return nullptr;
|
||||
|
||||
if (struct_ptr_type->id == TypeTableEntryIdPointer &&
|
||||
if (struct_ptr_type->id == ZigTypeIdPointer &&
|
||||
struct_ptr_type->data.pointer.unaligned_bit_count != 0)
|
||||
{
|
||||
return struct_ptr;
|
||||
@@ -3175,10 +3502,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
|
||||
static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnionFieldPtr *instruction)
|
||||
{
|
||||
TypeTableEntry *union_ptr_type = instruction->union_ptr->value.type;
|
||||
assert(union_ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *union_type = union_ptr_type->data.pointer.child_type;
|
||||
assert(union_type->id == TypeTableEntryIdUnion);
|
||||
ZigType *union_ptr_type = instruction->union_ptr->value.type;
|
||||
assert(union_ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *union_type = union_ptr_type->data.pointer.child_type;
|
||||
assert(union_type->id == ZigTypeIdUnion);
|
||||
|
||||
TypeUnionField *field = instruction->field;
|
||||
|
||||
@@ -3304,7 +3631,7 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||
}
|
||||
|
||||
if (!is_return) {
|
||||
VariableTableEntry *variable = instruction->output_vars[i];
|
||||
ZigVar *variable = instruction->output_vars[i];
|
||||
assert(variable);
|
||||
param_types[param_index] = LLVMTypeOf(variable->value_ref);
|
||||
param_values[param_index] = variable->value_ref;
|
||||
@@ -3345,9 +3672,9 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||
return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLVMValueRef maybe_handle) {
|
||||
assert(maybe_type->id == TypeTableEntryIdOptional);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueRef maybe_handle) {
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
return maybe_handle;
|
||||
} else {
|
||||
@@ -3370,11 +3697,11 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
|
||||
static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapOptional *instruction)
|
||||
{
|
||||
TypeTableEntry *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type;
|
||||
assert(maybe_type->id == TypeTableEntryIdOptional);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *maybe_type = ptr_type->data.pointer.child_type;
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
|
||||
@@ -3401,7 +3728,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, BuiltinFnId fn_id) {
|
||||
static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnId fn_id) {
|
||||
ZigLLVMFnKey key = {};
|
||||
const char *fn_name;
|
||||
uint32_t n_args;
|
||||
@@ -3444,7 +3771,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, Bui
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstructionClz *instruction) {
|
||||
TypeTableEntry *int_type = instruction->value->value.type;
|
||||
ZigType *int_type = instruction->value->value.type;
|
||||
LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz);
|
||||
LLVMValueRef operand = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef params[] {
|
||||
@@ -3456,7 +3783,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstru
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstructionCtz *instruction) {
|
||||
TypeTableEntry *int_type = instruction->value->value.type;
|
||||
ZigType *int_type = instruction->value->value.type;
|
||||
LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz);
|
||||
LLVMValueRef operand = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef params[] {
|
||||
@@ -3468,7 +3795,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
|
||||
TypeTableEntry *int_type = instruction->value->value.type;
|
||||
ZigType *int_type = instruction->value->value.type;
|
||||
LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
|
||||
LLVMValueRef operand = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, &operand, 1, "");
|
||||
@@ -3545,15 +3872,15 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI
|
||||
return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef get_enum_tag_name_function(CodeGen *g, TypeTableEntry *enum_type) {
|
||||
assert(enum_type->id == TypeTableEntryIdEnum);
|
||||
static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
|
||||
assert(enum_type->id == ZigTypeIdEnum);
|
||||
if (enum_type->data.enumeration.name_function)
|
||||
return enum_type->data.enumeration.name_function;
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
|
||||
ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *u8_slice_type = get_slice_type(g, u8_ptr_type);
|
||||
TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type;
|
||||
ZigType *u8_slice_type = get_slice_type(g, u8_ptr_type);
|
||||
ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type;
|
||||
|
||||
LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(u8_slice_type->type_ref, 0),
|
||||
&tag_int_type->type_ref, 1, false);
|
||||
@@ -3571,7 +3898,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, TypeTableEntry *enum_
|
||||
|
||||
LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
|
||||
LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
|
||||
FnTableEntry *prev_cur_fn = g->cur_fn;
|
||||
ZigFn *prev_cur_fn = g->cur_fn;
|
||||
LLVMValueRef prev_cur_fn_val = g->cur_fn_val;
|
||||
|
||||
LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
|
||||
@@ -3586,7 +3913,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, TypeTableEntry *enum_
|
||||
LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, tag_int_value, bad_value_block, field_count);
|
||||
|
||||
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef array_ptr_indices[] = {
|
||||
LLVMConstNull(usize->type_ref),
|
||||
LLVMConstNull(usize->type_ref),
|
||||
@@ -3643,8 +3970,8 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, TypeTableEntry *enum_
|
||||
static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionTagName *instruction)
|
||||
{
|
||||
TypeTableEntry *enum_type = instruction->target->value.type;
|
||||
assert(enum_type->id == TypeTableEntryIdEnum);
|
||||
ZigType *enum_type = instruction->target->value.type;
|
||||
assert(enum_type->id == ZigTypeIdEnum);
|
||||
|
||||
LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type);
|
||||
|
||||
@@ -3656,10 +3983,10 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
|
||||
static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionFieldParentPtr *instruction)
|
||||
{
|
||||
TypeTableEntry *container_ptr_type = instruction->base.value.type;
|
||||
assert(container_ptr_type->id == TypeTableEntryIdPointer);
|
||||
ZigType *container_ptr_type = instruction->base.value.type;
|
||||
assert(container_ptr_type->id == ZigTypeIdPointer);
|
||||
|
||||
TypeTableEntry *container_type = container_ptr_type->data.pointer.child_type;
|
||||
ZigType *container_type = container_ptr_type->data.pointer.child_type;
|
||||
|
||||
size_t byte_offset = LLVMOffsetOfElement(g->target_data_ref,
|
||||
container_type->type_ref, instruction->field->gen_index);
|
||||
@@ -3669,7 +3996,7 @@ static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executa
|
||||
if (byte_offset == 0) {
|
||||
return LLVMBuildBitCast(g->builder, field_ptr_val, container_ptr_type->type_ref, "");
|
||||
} else {
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
|
||||
LLVMValueRef field_ptr_int = LLVMBuildPtrToInt(g->builder, field_ptr_val,
|
||||
usize->type_ref, "");
|
||||
@@ -3690,32 +4017,32 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
|
||||
return target_val;
|
||||
}
|
||||
|
||||
TypeTableEntry *target_type = instruction->base.value.type;
|
||||
ZigType *target_type = instruction->base.value.type;
|
||||
uint32_t align_bytes;
|
||||
LLVMValueRef ptr_val;
|
||||
|
||||
if (target_type->id == TypeTableEntryIdPointer) {
|
||||
if (target_type->id == ZigTypeIdPointer) {
|
||||
align_bytes = target_type->data.pointer.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdFn) {
|
||||
} else if (target_type->id == ZigTypeIdFn) {
|
||||
align_bytes = target_type->data.fn.fn_type_id.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdPointer)
|
||||
} else if (target_type->id == ZigTypeIdOptional &&
|
||||
target_type->data.maybe.child_type->id == ZigTypeIdPointer)
|
||||
{
|
||||
align_bytes = target_type->data.maybe.child_type->data.pointer.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdFn)
|
||||
} else if (target_type->id == ZigTypeIdOptional &&
|
||||
target_type->data.maybe.child_type->id == ZigTypeIdFn)
|
||||
{
|
||||
align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
|
||||
ptr_val = target_val;
|
||||
} else if (target_type->id == TypeTableEntryIdOptional &&
|
||||
target_type->data.maybe.child_type->id == TypeTableEntryIdPromise)
|
||||
} else if (target_type->id == ZigTypeIdOptional &&
|
||||
target_type->data.maybe.child_type->id == ZigTypeIdPromise)
|
||||
{
|
||||
zig_panic("TODO audit this function");
|
||||
} else if (target_type->id == TypeTableEntryIdStruct && target_type->data.structure.is_slice) {
|
||||
TypeTableEntry *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
} else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {
|
||||
ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
align_bytes = slice_ptr_type->data.pointer.alignment;
|
||||
|
||||
size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
@@ -3727,7 +4054,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
|
||||
|
||||
assert(align_bytes != 1);
|
||||
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef ptr_as_int_val = LLVMBuildPtrToInt(g->builder, ptr_val, usize->type_ref, "");
|
||||
LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->type_ref, align_bytes - 1, false);
|
||||
LLVMValueRef anded_val = LLVMBuildAnd(g->builder, ptr_as_int_val, alignment_minus_1, "");
|
||||
@@ -3751,7 +4078,7 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu
|
||||
{
|
||||
LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
|
||||
if (cur_err_ret_trace_val == nullptr) {
|
||||
TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
|
||||
ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
|
||||
return LLVMConstNull(ptr_to_stack_trace_type->type_ref);
|
||||
}
|
||||
return cur_err_ret_trace_val;
|
||||
@@ -3811,9 +4138,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
|
||||
LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
|
||||
success_order, failure_order, instruction->is_weak);
|
||||
|
||||
TypeTableEntry *maybe_type = instruction->base.value.type;
|
||||
assert(maybe_type->id == TypeTableEntryIdOptional);
|
||||
TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
|
||||
ZigType *maybe_type = instruction->base.value.type;
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
@@ -3843,8 +4170,8 @@ static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInst
|
||||
|
||||
static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) {
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
TypeTableEntry *dest_type = instruction->base.value.type;
|
||||
TypeTableEntry *src_type = instruction->target->value.type;
|
||||
ZigType *dest_type = instruction->base.value.type;
|
||||
ZigType *src_type = instruction->target->value.type;
|
||||
if (dest_type == src_type) {
|
||||
// no-op
|
||||
return target_val;
|
||||
@@ -3865,8 +4192,8 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
|
||||
|
||||
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
|
||||
|
||||
TypeTableEntry *ptr_type = instruction->dest_ptr->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
ZigType *ptr_type = instruction->dest_ptr->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
|
||||
ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);
|
||||
return nullptr;
|
||||
@@ -3882,11 +4209,11 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
|
||||
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
|
||||
LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
|
||||
|
||||
TypeTableEntry *dest_ptr_type = instruction->dest_ptr->value.type;
|
||||
TypeTableEntry *src_ptr_type = instruction->src_ptr->value.type;
|
||||
ZigType *dest_ptr_type = instruction->dest_ptr->value.type;
|
||||
ZigType *src_ptr_type = instruction->src_ptr->value.type;
|
||||
|
||||
assert(dest_ptr_type->id == TypeTableEntryIdPointer);
|
||||
assert(src_ptr_type->id == TypeTableEntryIdPointer);
|
||||
assert(dest_ptr_type->id == ZigTypeIdPointer);
|
||||
assert(src_ptr_type->id == ZigTypeIdPointer);
|
||||
|
||||
bool is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile);
|
||||
|
||||
@@ -3899,19 +4226,19 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
assert(instruction->tmp_ptr);
|
||||
|
||||
LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);
|
||||
TypeTableEntry *array_ptr_type = instruction->ptr->value.type;
|
||||
assert(array_ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type;
|
||||
ZigType *array_ptr_type = instruction->ptr->value.type;
|
||||
assert(array_ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *array_type = array_ptr_type->data.pointer.child_type;
|
||||
LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
|
||||
|
||||
LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
|
||||
|
||||
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
|
||||
|
||||
if (array_type->id == TypeTableEntryIdArray ||
|
||||
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
|
||||
if (array_type->id == ZigTypeIdArray ||
|
||||
(array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
|
||||
{
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
if (array_type->id == ZigTypeIdPointer) {
|
||||
array_type = array_type->data.pointer.child_type;
|
||||
}
|
||||
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
|
||||
@@ -3952,7 +4279,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
|
||||
|
||||
return tmp_struct_ptr;
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
} else if (array_type->id == ZigTypeIdPointer) {
|
||||
assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
|
||||
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
|
||||
LLVMValueRef end_val = ir_llvm_value(g, instruction->end);
|
||||
@@ -3974,7 +4301,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
|
||||
|
||||
return tmp_struct_ptr;
|
||||
} else if (array_type->id == TypeTableEntryIdStruct) {
|
||||
} else if (array_type->id == ZigTypeIdStruct) {
|
||||
assert(array_type->data.structure.is_slice);
|
||||
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
|
||||
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
|
||||
@@ -4050,7 +4377,7 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) {
|
||||
if (g->frame_address_fn_val)
|
||||
return g->frame_address_fn_val;
|
||||
|
||||
TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
ZigType *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
|
||||
LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref,
|
||||
&g->builtin_types.entry_i32->type_ref, 1, false);
|
||||
@@ -4088,8 +4415,8 @@ static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
|
||||
TypeTableEntry *int_type = instruction->result_ptr_type;
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
ZigType *int_type = instruction->result_ptr_type;
|
||||
assert(int_type->id == ZigTypeIdInt);
|
||||
|
||||
LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
|
||||
LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
|
||||
@@ -4128,8 +4455,8 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
|
||||
return render_shl_with_overflow(g, instruction);
|
||||
}
|
||||
|
||||
TypeTableEntry *int_type = instruction->result_ptr_type;
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
ZigType *int_type = instruction->result_ptr_type;
|
||||
assert(int_type->id == ZigTypeIdInt);
|
||||
|
||||
LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
|
||||
|
||||
@@ -4151,8 +4478,8 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
|
||||
TypeTableEntry *err_union_type = instruction->value->value.type;
|
||||
TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type;
|
||||
ZigType *err_union_type = instruction->value->value.type;
|
||||
ZigType *payload_type = err_union_type->data.error_union.payload_type;
|
||||
LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);
|
||||
|
||||
LLVMValueRef err_val;
|
||||
@@ -4168,10 +4495,10 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
|
||||
TypeTableEntry *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type;
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *err_union_type = ptr_type->data.pointer.child_type;
|
||||
ZigType *payload_type = err_union_type->data.error_union.payload_type;
|
||||
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
|
||||
|
||||
@@ -4184,10 +4511,10 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
|
||||
TypeTableEntry *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type;
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *err_union_type = ptr_type->data.pointer.child_type;
|
||||
ZigType *payload_type = err_union_type->data.error_union.payload_type;
|
||||
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
|
||||
|
||||
@@ -4223,11 +4550,11 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
|
||||
assert(wanted_type->id == TypeTableEntryIdOptional);
|
||||
assert(wanted_type->id == ZigTypeIdOptional);
|
||||
|
||||
TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
|
||||
ZigType *child_type = wanted_type->data.maybe.child_type;
|
||||
|
||||
if (child_type->zero_bits) {
|
||||
return LLVMConstInt(LLVMInt1Type(), 1, false);
|
||||
@@ -4250,12 +4577,12 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
|
||||
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
|
||||
assert(wanted_type->id == ZigTypeIdErrorUnion);
|
||||
|
||||
TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type;
|
||||
TypeTableEntry *err_set_type = wanted_type->data.error_union.err_set_type;
|
||||
ZigType *payload_type = wanted_type->data.error_union.payload_type;
|
||||
ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
|
||||
|
||||
LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
|
||||
|
||||
@@ -4271,12 +4598,12 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {
|
||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
|
||||
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
|
||||
assert(wanted_type->id == ZigTypeIdErrorUnion);
|
||||
|
||||
TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type;
|
||||
TypeTableEntry *err_set_type = wanted_type->data.error_union.err_set_type;
|
||||
ZigType *payload_type = wanted_type->data.error_union.payload_type;
|
||||
ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
|
||||
|
||||
if (!type_has_bits(err_set_type)) {
|
||||
return ir_llvm_value(g, instruction->value);
|
||||
@@ -4301,10 +4628,10 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
|
||||
TypeTableEntry *union_type = instruction->value->value.type;
|
||||
ZigType *union_type = instruction->value->value.type;
|
||||
assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
|
||||
|
||||
TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
|
||||
ZigType *tag_type = union_type->data.unionation.tag_type;
|
||||
if (!type_has_bits(tag_type))
|
||||
return nullptr;
|
||||
|
||||
@@ -4314,7 +4641,7 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
|
||||
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val,
|
||||
union_type->data.unionation.gen_tag_index, "");
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false);
|
||||
ZigType *ptr_type = get_pointer_to_type(g, tag_type, false);
|
||||
return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
|
||||
}
|
||||
|
||||
@@ -4331,7 +4658,7 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
|
||||
|
||||
uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
|
||||
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
|
||||
ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
|
||||
false, false, PtrLenSingle, field_align_bytes,
|
||||
(uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count);
|
||||
|
||||
@@ -4347,14 +4674,14 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
|
||||
return nullptr;
|
||||
|
||||
uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
|
||||
ZigType *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
|
||||
false, false, PtrLenSingle, field_align_bytes,
|
||||
0, 0);
|
||||
|
||||
LLVMValueRef uncasted_union_ptr;
|
||||
// Even if safety is off in this block, if the union type has the safety field, we have to populate it
|
||||
// correctly. Otherwise safety code somewhere other than here could fail.
|
||||
TypeTableEntry *union_type = instruction->union_type;
|
||||
ZigType *union_type = instruction->union_type;
|
||||
if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
|
||||
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
|
||||
union_type->data.unionation.gen_tag_index, "");
|
||||
@@ -4380,14 +4707,14 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
|
||||
static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionContainerInitList *instruction)
|
||||
{
|
||||
TypeTableEntry *array_type = instruction->base.value.type;
|
||||
assert(array_type->id == TypeTableEntryIdArray);
|
||||
ZigType *array_type = instruction->base.value.type;
|
||||
assert(array_type->id == ZigTypeIdArray);
|
||||
LLVMValueRef tmp_array_ptr = instruction->tmp_ptr;
|
||||
assert(tmp_array_ptr);
|
||||
|
||||
size_t field_count = instruction->item_count;
|
||||
|
||||
TypeTableEntry *child_type = array_type->data.array.child_type;
|
||||
ZigType *child_type = array_type->data.array.child_type;
|
||||
for (size_t i = 0; i < field_count; i += 1) {
|
||||
LLVMValueRef elem_val = ir_llvm_value(g, instruction->items[i]);
|
||||
LLVMValueRef indices[] = {
|
||||
@@ -4511,13 +4838,13 @@ static LLVMValueRef ir_render_coro_promise(CodeGen *g, IrExecutable *executable,
|
||||
return LLVMBuildBitCast(g->builder, uncasted_result, instruction->base.value.type->type_ref, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_fn_type_ref, TypeTableEntry *fn_type) {
|
||||
static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_fn_type_ref, ZigType *fn_type) {
|
||||
if (g->coro_alloc_helper_fn_val != nullptr)
|
||||
return g->coro_alloc_helper_fn_val;
|
||||
|
||||
assert(fn_type->id == TypeTableEntryIdFn);
|
||||
assert(fn_type->id == ZigTypeIdFn);
|
||||
|
||||
TypeTableEntry *ptr_to_err_code_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
|
||||
ZigType *ptr_to_err_code_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
|
||||
|
||||
LLVMTypeRef alloc_raw_fn_type_ref = LLVMGetElementType(alloc_fn_type_ref);
|
||||
LLVMTypeRef *alloc_fn_arg_types = allocate<LLVMTypeRef>(LLVMCountParamTypes(alloc_raw_fn_type_ref));
|
||||
@@ -4545,7 +4872,7 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
|
||||
|
||||
LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
|
||||
LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
|
||||
FnTableEntry *prev_cur_fn = g->cur_fn;
|
||||
ZigFn *prev_cur_fn = g->cur_fn;
|
||||
LLVMValueRef prev_cur_fn_val = g->cur_fn_val;
|
||||
|
||||
LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
|
||||
@@ -4596,9 +4923,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_payload_index, "");
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
|
||||
ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *slice_type = get_slice_type(g, u8_ptr_type);
|
||||
ZigType *slice_type = get_slice_type(g, u8_ptr_type);
|
||||
size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, payload_ptr, ptr_field_index, "");
|
||||
LLVMValueRef ptr_val = LLVMBuildLoad(g->builder, ptr_field_ptr, "");
|
||||
@@ -4643,8 +4970,8 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionAtomicRmw *instruction)
|
||||
{
|
||||
bool is_signed;
|
||||
TypeTableEntry *operand_type = instruction->operand->value.type;
|
||||
if (operand_type->id == TypeTableEntryIdInt) {
|
||||
ZigType *operand_type = instruction->operand->value.type;
|
||||
if (operand_type->id == ZigTypeIdInt) {
|
||||
is_signed = operand_type->data.integral.is_signed;
|
||||
} else {
|
||||
is_signed = false;
|
||||
@@ -4699,7 +5026,7 @@ static LLVMValueRef ir_render_mark_err_ret_trace_ptr(CodeGen *g, IrExecutable *e
|
||||
|
||||
static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstructionSqrt *instruction) {
|
||||
LLVMValueRef op = ir_llvm_value(g, instruction->op);
|
||||
assert(instruction->base.value.type->id == TypeTableEntryIdFloat);
|
||||
assert(instruction->base.value.type->id == ZigTypeIdFloat);
|
||||
LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdSqrt);
|
||||
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||
}
|
||||
@@ -4780,6 +5107,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdFromBytes:
|
||||
case IrInstructionIdToBytes:
|
||||
case IrInstructionIdEnumToInt:
|
||||
case IrInstructionIdCheckRuntimeScope:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdReturn:
|
||||
@@ -4946,7 +5274,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
|
||||
static void ir_render(CodeGen *g, ZigFn *fn_entry) {
|
||||
assert(fn_entry);
|
||||
|
||||
IrExecutable *executable = &fn_entry->analyzed_executable;
|
||||
@@ -4999,14 +5327,14 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
|
||||
|
||||
LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
|
||||
if (el_type == LLVMArrayTypeKind) {
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(usize->type_ref),
|
||||
LLVMConstInt(usize->type_ref, index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
} else if (el_type == LLVMStructTypeKind) {
|
||||
TypeTableEntry *u32 = g->builtin_types.entry_u32;
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, index, false),
|
||||
@@ -5022,7 +5350,7 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
|
||||
ConstParent *parent = &struct_const_val->data.x_struct.parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
|
||||
|
||||
TypeTableEntry *u32 = g->builtin_types.entry_u32;
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, field_index, false),
|
||||
@@ -5034,7 +5362,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un
|
||||
ConstParent *parent = &union_const_val->data.x_union.parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
|
||||
|
||||
TypeTableEntry *u32 = g->builtin_types.entry_u32;
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, 0, false), // TODO test const union with more aligned tag type than payload
|
||||
@@ -5052,59 +5380,59 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
break;
|
||||
}
|
||||
|
||||
TypeTableEntry *type_entry = const_val->type;
|
||||
ZigType *type_entry = const_val->type;
|
||||
assert(!type_entry->zero_bits);
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdOpaque:
|
||||
case ZigTypeIdInvalid:
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdUnreachable:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdNamespace:
|
||||
case ZigTypeIdBlock:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdVoid:
|
||||
case ZigTypeIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdBool:
|
||||
case ZigTypeIdBool:
|
||||
return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
|
||||
case TypeTableEntryIdEnum:
|
||||
case ZigTypeIdEnum:
|
||||
{
|
||||
assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
|
||||
LLVMValueRef int_val = gen_const_val(g, const_val, "");
|
||||
return LLVMConstZExt(int_val, big_int_type_ref);
|
||||
}
|
||||
case TypeTableEntryIdInt:
|
||||
case ZigTypeIdInt:
|
||||
{
|
||||
LLVMValueRef int_val = gen_const_val(g, const_val, "");
|
||||
return LLVMConstZExt(int_val, big_int_type_ref);
|
||||
}
|
||||
case TypeTableEntryIdFloat:
|
||||
case ZigTypeIdFloat:
|
||||
{
|
||||
LLVMValueRef float_val = gen_const_val(g, const_val, "");
|
||||
LLVMValueRef int_val = LLVMConstFPToUI(float_val,
|
||||
LLVMIntType((unsigned)type_entry->data.floating.bit_count));
|
||||
return LLVMConstZExt(int_val, big_int_type_ref);
|
||||
}
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdPromise:
|
||||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdOptional:
|
||||
case ZigTypeIdPromise:
|
||||
{
|
||||
LLVMValueRef ptr_val = gen_const_val(g, const_val, "");
|
||||
LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
|
||||
return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);
|
||||
}
|
||||
case TypeTableEntryIdArray:
|
||||
case ZigTypeIdArray:
|
||||
zig_panic("TODO bit pack an array");
|
||||
case TypeTableEntryIdUnion:
|
||||
case ZigTypeIdUnion:
|
||||
zig_panic("TODO bit pack a union");
|
||||
case TypeTableEntryIdStruct:
|
||||
case ZigTypeIdStruct:
|
||||
{
|
||||
assert(type_entry->data.structure.layout == ContainerLayoutPacked);
|
||||
bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
|
||||
@@ -5137,7 +5465,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
|
||||
// We have this because union constants can't be represented by the official union type,
|
||||
// and this property bubbles up in whatever aggregate type contains a union constant
|
||||
static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef val) {
|
||||
static bool is_llvm_value_unnamed_type(ZigType *type_entry, LLVMValueRef val) {
|
||||
return LLVMTypeOf(val) != type_entry->type_ref;
|
||||
}
|
||||
|
||||
@@ -5162,10 +5490,10 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
|
||||
size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
|
||||
assert(array_const_val->type->id == TypeTableEntryIdArray);
|
||||
assert(array_const_val->type->id == ZigTypeIdArray);
|
||||
if (array_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
|
||||
const_val->type->type_ref);
|
||||
render_const_val_global(g, const_val, "");
|
||||
@@ -5182,10 +5510,10 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
|
||||
assert(struct_const_val->type->id == TypeTableEntryIdStruct);
|
||||
assert(struct_const_val->type->id == ZigTypeIdStruct);
|
||||
if (struct_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
|
||||
const_val->type->type_ref);
|
||||
render_const_val_global(g, const_val, "");
|
||||
@@ -5205,7 +5533,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
|
||||
const_val->type->type_ref);
|
||||
render_const_val_global(g, const_val, "");
|
||||
@@ -5218,7 +5546,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
|
||||
TypeTableEntry *type_entry = const_val->type;
|
||||
ZigType *type_entry = const_val->type;
|
||||
assert(!type_entry->zero_bits);
|
||||
|
||||
switch (const_val->special) {
|
||||
@@ -5231,13 +5559,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
}
|
||||
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInt:
|
||||
case ZigTypeIdInt:
|
||||
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case ZigTypeIdErrorSet:
|
||||
assert(const_val->data.x_err_set != nullptr);
|
||||
return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
|
||||
const_val->data.x_err_set->value, false);
|
||||
case TypeTableEntryIdFloat:
|
||||
case ZigTypeIdFloat:
|
||||
switch (type_entry->data.floating.bit_count) {
|
||||
case 16:
|
||||
return LLVMConstReal(type_entry->type_ref, zig_f16_to_double(const_val->data.x_f16));
|
||||
@@ -5257,15 +5585,15 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
case TypeTableEntryIdBool:
|
||||
case ZigTypeIdBool:
|
||||
if (const_val->data.x_bool) {
|
||||
return LLVMConstAllOnes(LLVMInt1Type());
|
||||
} else {
|
||||
return LLVMConstNull(LLVMInt1Type());
|
||||
}
|
||||
case TypeTableEntryIdOptional:
|
||||
case ZigTypeIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
ZigType *child_type = type_entry->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
|
||||
} else if (type_is_codegen_pointer(child_type)) {
|
||||
@@ -5296,7 +5624,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
}
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdStruct:
|
||||
case ZigTypeIdStruct:
|
||||
{
|
||||
LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
|
||||
size_t src_field_count = type_entry->data.structure.src_field_count;
|
||||
@@ -5372,7 +5700,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count);
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdArray:
|
||||
case ZigTypeIdArray:
|
||||
{
|
||||
uint64_t len = type_entry->data.array.len;
|
||||
if (const_val->data.x_array.special == ConstArraySpecialUndef) {
|
||||
@@ -5394,12 +5722,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
return LLVMConstArray(element_type_ref, values, (unsigned)len);
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdUnion:
|
||||
case ZigTypeIdUnion:
|
||||
{
|
||||
LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
|
||||
|
||||
if (type_entry->data.unionation.gen_field_count == 0) {
|
||||
if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
|
||||
if (type_entry->data.unionation.tag_type == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
|
||||
@@ -5458,18 +5786,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
|
||||
}
|
||||
|
||||
case TypeTableEntryIdEnum:
|
||||
case ZigTypeIdEnum:
|
||||
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
|
||||
case TypeTableEntryIdFn:
|
||||
case ZigTypeIdFn:
|
||||
assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction);
|
||||
assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
|
||||
return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry);
|
||||
case TypeTableEntryIdPointer:
|
||||
case ZigTypeIdPointer:
|
||||
return gen_const_val_ptr(g, const_val, name);
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case ZigTypeIdErrorUnion:
|
||||
{
|
||||
TypeTableEntry *payload_type = type_entry->data.error_union.payload_type;
|
||||
TypeTableEntry *err_set_type = type_entry->data.error_union.err_set_type;
|
||||
ZigType *payload_type = type_entry->data.error_union.payload_type;
|
||||
ZigType *err_set_type = type_entry->data.error_union.err_set_type;
|
||||
if (!type_has_bits(payload_type)) {
|
||||
assert(type_has_bits(err_set_type));
|
||||
uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
|
||||
@@ -5502,21 +5830,21 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
}
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdVoid:
|
||||
case ZigTypeIdVoid:
|
||||
return nullptr;
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
case TypeTableEntryIdPromise:
|
||||
case ZigTypeIdInvalid:
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdUnreachable:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdNamespace:
|
||||
case ZigTypeIdBlock:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdOpaque:
|
||||
case ZigTypeIdPromise:
|
||||
zig_unreachable();
|
||||
|
||||
}
|
||||
@@ -5559,9 +5887,9 @@ static void generate_error_name_table(CodeGen *g) {
|
||||
|
||||
assert(g->errors_by_index.length > 0);
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
ZigType *str_type = get_slice_type(g, u8_ptr_type);
|
||||
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length);
|
||||
values[0] = LLVMGetUndef(str_type->type_ref);
|
||||
@@ -5597,7 +5925,7 @@ static void generate_error_name_table(CodeGen *g) {
|
||||
LLVMSetAlignment(g->err_name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(err_name_table_init)));
|
||||
}
|
||||
|
||||
static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) {
|
||||
static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) {
|
||||
IrExecutable *executable = &fn->analyzed_executable;
|
||||
assert(executable->basic_block_list.length > 0);
|
||||
for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
|
||||
@@ -5608,8 +5936,8 @@ static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) {
|
||||
LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block);
|
||||
}
|
||||
|
||||
static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef init_val,
|
||||
TypeTableEntry *type_entry)
|
||||
static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
|
||||
ZigType *type_entry)
|
||||
{
|
||||
if (g->strip_debug_symbols) {
|
||||
return;
|
||||
@@ -5630,33 +5958,16 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini
|
||||
// TODO ^^ make an actual global variable
|
||||
}
|
||||
|
||||
static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const char *name, uint32_t alignment) {
|
||||
assert(alignment > 0);
|
||||
LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
|
||||
LLVMSetAlignment(result, alignment);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ensure_cache_dir(CodeGen *g) {
|
||||
int err;
|
||||
if ((err = os_make_path(g->cache_dir))) {
|
||||
if ((err = os_make_path(&g->cache_dir))) {
|
||||
zig_panic("unable to make cache dir: %s", err_str(err));
|
||||
}
|
||||
}
|
||||
|
||||
static void report_errors_and_maybe_exit(CodeGen *g) {
|
||||
if (g->errors.length != 0) {
|
||||
for (size_t i = 0; i < g->errors.length; i += 1) {
|
||||
ErrorMsg *err = g->errors.at(i);
|
||||
print_err_msg(err, g->err_color);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void validate_inline_fns(CodeGen *g) {
|
||||
for (size_t i = 0; i < g->inline_fns.length; i += 1) {
|
||||
FnTableEntry *fn_entry = g->inline_fns.at(i);
|
||||
ZigFn *fn_entry = g->inline_fns.at(i);
|
||||
LLVMValueRef fn_val = LLVMGetNamedFunction(g->module, fn_entry->llvm_name);
|
||||
if (fn_val != nullptr) {
|
||||
add_node_error(g, fn_entry->proto_node, buf_sprintf("unable to inline function"));
|
||||
@@ -5697,13 +6008,13 @@ static void do_code_gen(CodeGen *g) {
|
||||
// Generate module level variables
|
||||
for (size_t i = 0; i < g->global_vars.length; i += 1) {
|
||||
TldVar *tld_var = g->global_vars.at(i);
|
||||
VariableTableEntry *var = tld_var->var;
|
||||
ZigVar *var = tld_var->var;
|
||||
|
||||
if (var->value->type->id == TypeTableEntryIdComptimeFloat) {
|
||||
if (var->value->type->id == ZigTypeIdComptimeFloat) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
TypeTableEntry *var_type = g->builtin_types.entry_f128;
|
||||
ZigType *var_type = g->builtin_types.entry_f128;
|
||||
ConstExprValue coerced_value;
|
||||
coerced_value.special = ConstValSpecialStatic;
|
||||
coerced_value.type = var_type;
|
||||
@@ -5713,7 +6024,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var->value->type->id == TypeTableEntryIdComptimeInt) {
|
||||
if (var->value->type->id == ZigTypeIdComptimeInt) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
@@ -5721,7 +6032,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
if (bits_needed < 8) {
|
||||
bits_needed = 8;
|
||||
}
|
||||
TypeTableEntry *var_type = get_int_type(g, const_val->data.x_bigint.is_negative, bits_needed);
|
||||
ZigType *var_type = get_int_type(g, const_val->data.x_bigint.is_negative, bits_needed);
|
||||
LLVMValueRef init_val = bigint_to_llvm_const(var_type->type_ref, &const_val->data.x_bigint);
|
||||
gen_global_var(g, var, init_val, var_type);
|
||||
continue;
|
||||
@@ -5761,7 +6072,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
LLVMSetAlignment(global_value, var->align_bytes);
|
||||
|
||||
// TODO debug info for function pointers
|
||||
if (var->gen_is_const && var->value->type->id != TypeTableEntryIdFn) {
|
||||
if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {
|
||||
gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
|
||||
}
|
||||
|
||||
@@ -5773,12 +6084,15 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
// Generate function definitions.
|
||||
for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {
|
||||
FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i);
|
||||
ZigFn *fn_table_entry = g->fn_defs.at(fn_i);
|
||||
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
|
||||
CallingConvention cc = fn_type_id->cc;
|
||||
bool is_c_abi = cc == CallingConventionC;
|
||||
|
||||
LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
|
||||
g->cur_fn = fn_table_entry;
|
||||
g->cur_fn_val = fn;
|
||||
TypeTableEntry *return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
|
||||
ZigType *return_type = fn_type_id->return_type;
|
||||
if (handle_is_ptr(return_type)) {
|
||||
g->cur_ret_ptr = LLVMGetParam(fn, 0);
|
||||
} else {
|
||||
@@ -5797,11 +6111,11 @@ static void do_code_gen(CodeGen *g) {
|
||||
}
|
||||
|
||||
// error return tracing setup
|
||||
bool is_async = fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
|
||||
bool is_async = cc == CallingConventionAsync;
|
||||
bool have_err_ret_trace_stack = g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn && !is_async && !have_err_ret_trace_arg;
|
||||
LLVMValueRef err_ret_array_val = nullptr;
|
||||
if (have_err_ret_trace_stack) {
|
||||
TypeTableEntry *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);
|
||||
ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);
|
||||
err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
|
||||
g->cur_err_ret_trace_val_stack = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type));
|
||||
} else {
|
||||
@@ -5812,14 +6126,14 @@ static void do_code_gen(CodeGen *g) {
|
||||
for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {
|
||||
IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
|
||||
LLVMValueRef *slot;
|
||||
TypeTableEntry *slot_type = instruction->value.type;
|
||||
ZigType *slot_type = instruction->value.type;
|
||||
if (instruction->id == IrInstructionIdCast) {
|
||||
IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
|
||||
slot = &cast_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdRef) {
|
||||
IrInstructionRef *ref_instruction = (IrInstructionRef *)instruction;
|
||||
slot = &ref_instruction->tmp_ptr;
|
||||
assert(instruction->value.type->id == TypeTableEntryIdPointer);
|
||||
assert(instruction->value.type->id == ZigTypeIdPointer);
|
||||
slot_type = instruction->value.type->data.pointer.child_type;
|
||||
} else if (instruction->id == IrInstructionIdContainerInitList) {
|
||||
IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
|
||||
@@ -5856,9 +6170,17 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
|
||||
|
||||
unsigned gen_i_init = want_first_arg_sret(g, fn_type_id) ? 1 : 0;
|
||||
|
||||
// create debug variable declarations for variables and allocate all local variables
|
||||
FnWalk fn_walk_var = {};
|
||||
fn_walk_var.id = FnWalkIdVars;
|
||||
fn_walk_var.data.vars.import = import;
|
||||
fn_walk_var.data.vars.fn = fn_table_entry;
|
||||
fn_walk_var.data.vars.llvm_fn = fn;
|
||||
fn_walk_var.data.vars.gen_i = gen_i_init;
|
||||
for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
|
||||
VariableTableEntry *var = fn_table_entry->variable_list.at(var_i);
|
||||
ZigVar *var = fn_table_entry->variable_list.at(var_i);
|
||||
|
||||
if (!type_has_bits(var->value->type)) {
|
||||
continue;
|
||||
@@ -5875,9 +6197,12 @@ static void do_code_gen(CodeGen *g) {
|
||||
buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
|
||||
var->value->type->di_type, !g->strip_debug_symbols, 0);
|
||||
|
||||
} else if (is_c_abi) {
|
||||
fn_walk_var.data.vars.var = var;
|
||||
iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index);
|
||||
} else {
|
||||
assert(var->gen_arg_index != SIZE_MAX);
|
||||
TypeTableEntry *gen_type;
|
||||
ZigType *gen_type;
|
||||
FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
|
||||
|
||||
if (handle_is_ptr(var->value->type)) {
|
||||
@@ -5903,7 +6228,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
// finishing error return trace setup. we have to do this after all the allocas.
|
||||
if (have_err_ret_trace_stack) {
|
||||
TypeTableEntry *usize = g->builtin_types.entry_usize;
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
|
||||
LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, "");
|
||||
gen_store_untyped(g, LLVMConstNull(usize->type_ref), index_field_ptr, 0, false);
|
||||
@@ -5911,14 +6236,14 @@ static void do_code_gen(CodeGen *g) {
|
||||
size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
|
||||
LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, "");
|
||||
|
||||
TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
|
||||
ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
|
||||
size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, "");
|
||||
LLVMValueRef zero = LLVMConstNull(usize->type_ref);
|
||||
LLVMValueRef indices[] = {zero, zero};
|
||||
LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP(g->builder, err_ret_array_val,
|
||||
indices, 2, "");
|
||||
TypeTableEntry *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false);
|
||||
ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false);
|
||||
gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type);
|
||||
|
||||
size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index;
|
||||
@@ -5926,33 +6251,14 @@ static void do_code_gen(CodeGen *g) {
|
||||
gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false));
|
||||
}
|
||||
|
||||
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
|
||||
|
||||
// create debug variable declarations for parameters
|
||||
// rely on the first variables in the variable_list being parameters.
|
||||
size_t next_var_i = 0;
|
||||
for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
|
||||
FnGenParamInfo *info = &fn_table_entry->type_entry->data.fn.gen_param_info[param_i];
|
||||
if (info->gen_index == SIZE_MAX)
|
||||
continue;
|
||||
|
||||
VariableTableEntry *variable = fn_table_entry->variable_list.at(next_var_i);
|
||||
assert(variable->src_arg_index != SIZE_MAX);
|
||||
next_var_i += 1;
|
||||
|
||||
assert(variable);
|
||||
assert(variable->value_ref);
|
||||
|
||||
if (!handle_is_ptr(variable->value->type)) {
|
||||
clear_debug_source_node(g);
|
||||
gen_store_untyped(g, LLVMGetParam(fn, (unsigned)variable->gen_arg_index), variable->value_ref,
|
||||
variable->align_bytes, false);
|
||||
}
|
||||
|
||||
if (variable->decl_node) {
|
||||
gen_var_debug_decl(g, variable);
|
||||
}
|
||||
}
|
||||
FnWalk fn_walk_init = {};
|
||||
fn_walk_init.id = FnWalkIdInits;
|
||||
fn_walk_init.data.inits.fn = fn_table_entry;
|
||||
fn_walk_init.data.inits.llvm_fn = fn;
|
||||
fn_walk_init.data.inits.gen_i = gen_i_init;
|
||||
walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init);
|
||||
|
||||
ir_render(g, fn_table_entry);
|
||||
|
||||
@@ -6007,7 +6313,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
}
|
||||
|
||||
Buf *output_path = buf_alloc();
|
||||
os_path_join(g->cache_dir, o_basename, output_path);
|
||||
os_path_join(&g->cache_dir, o_basename, output_path);
|
||||
ensure_cache_dir(g);
|
||||
|
||||
bool is_small = g->build_mode == BuildModeSmallRelease;
|
||||
@@ -6030,6 +6336,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
g->link_objects.append(output_path);
|
||||
break;
|
||||
|
||||
case EmitFileTypeLLVMIr:
|
||||
@@ -6039,6 +6346,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
g->link_objects.append(output_path);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -6080,51 +6388,51 @@ static const GlobalLinkageValue global_linkage_values[] = {
|
||||
static void define_builtin_types(CodeGen *g) {
|
||||
{
|
||||
// if this type is anywhere in the AST, we should never hit codegen.
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInvalid);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdInvalid);
|
||||
buf_init_from_str(&entry->name, "(invalid)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_invalid = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNamespace);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdNamespace);
|
||||
buf_init_from_str(&entry->name, "(namespace)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_namespace = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBlock);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdBlock);
|
||||
buf_init_from_str(&entry->name, "(block)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_block = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdComptimeFloat);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat);
|
||||
buf_init_from_str(&entry->name, "comptime_float");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_num_lit_float = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdComptimeInt);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdComptimeInt);
|
||||
buf_init_from_str(&entry->name, "comptime_int");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_num_lit_int = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefined);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdUndefined);
|
||||
buf_init_from_str(&entry->name, "(undefined)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_undef = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNull);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdNull);
|
||||
buf_init_from_str(&entry->name, "(null)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_null = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArgTuple);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdArgTuple);
|
||||
buf_init_from_str(&entry->name, "(args)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_arg_tuple = entry;
|
||||
@@ -6135,7 +6443,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id);
|
||||
bool is_signed = info->is_signed;
|
||||
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdInt);
|
||||
entry->type_ref = LLVMIntType(size_in_bits);
|
||||
|
||||
buf_init_from_str(&entry->name, info->name);
|
||||
@@ -6152,7 +6460,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
}
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdBool);
|
||||
entry->type_ref = LLVMInt1Type();
|
||||
buf_init_from_str(&entry->name, "bool");
|
||||
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
|
||||
@@ -6166,7 +6474,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
for (size_t sign_i = 0; sign_i < array_length(is_signed_list); sign_i += 1) {
|
||||
bool is_signed = is_signed_list[sign_i];
|
||||
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdInt);
|
||||
entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
|
||||
|
||||
const char u_or_i = is_signed ? 'i' : 'u';
|
||||
@@ -6193,8 +6501,8 @@ static void define_builtin_types(CodeGen *g) {
|
||||
const char *name,
|
||||
uint32_t bit_count,
|
||||
LLVMTypeRef type_ref,
|
||||
TypeTableEntry **field) {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
|
||||
ZigType **field) {
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdFloat);
|
||||
entry->type_ref = type_ref;
|
||||
buf_init_from_str(&entry->name, name);
|
||||
entry->data.floating.bit_count = bit_count;
|
||||
@@ -6213,7 +6521,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
add_fp_entry(g, "c_longdouble", 80, LLVMX86FP80Type(), &g->builtin_types.entry_c_longdouble);
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdVoid);
|
||||
entry->type_ref = LLVMVoidType();
|
||||
entry->zero_bits = true;
|
||||
buf_init_from_str(&entry->name, "void");
|
||||
@@ -6224,7 +6532,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdUnreachable);
|
||||
entry->type_ref = LLVMVoidType();
|
||||
entry->zero_bits = true;
|
||||
buf_init_from_str(&entry->name, "noreturn");
|
||||
@@ -6233,7 +6541,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdMetaType);
|
||||
buf_init_from_str(&entry->name, "type");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_type = entry;
|
||||
@@ -6255,7 +6563,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
}
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorSet);
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdErrorSet);
|
||||
buf_init_from_str(&entry->name, "error");
|
||||
entry->data.error_set.err_count = UINT32_MAX;
|
||||
|
||||
@@ -6277,7 +6585,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = get_promise_type(g, nullptr);
|
||||
ZigType *entry = get_promise_type(g, nullptr);
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
|
||||
@@ -6530,7 +6838,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
buf_appendf(contents, "pub const TypeId = enum {\n");
|
||||
size_t field_count = type_id_len();
|
||||
for (size_t i = 0; i < field_count; i += 1) {
|
||||
const TypeTableEntryId id = type_id_at_index(i);
|
||||
const ZigTypeId id = type_id_at_index(i);
|
||||
buf_appendf(contents, " %s,\n", type_id_name(id));
|
||||
}
|
||||
buf_appendf(contents, "};\n\n");
|
||||
@@ -6769,25 +7077,22 @@ static void define_builtin_compile_vars(CodeGen *g) {
|
||||
|
||||
const char *builtin_zig_basename = "builtin.zig";
|
||||
Buf *builtin_zig_path = buf_alloc();
|
||||
os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
|
||||
os_path_join(&g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
|
||||
|
||||
Buf *contents = codegen_generate_builtin_source(g);
|
||||
ensure_cache_dir(g);
|
||||
os_write_file(builtin_zig_path, contents);
|
||||
|
||||
int err;
|
||||
Buf *abs_full_path = buf_alloc();
|
||||
if ((err = os_path_real(builtin_zig_path, abs_full_path))) {
|
||||
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
Buf *resolved_path = buf_alloc();
|
||||
Buf *resolve_paths[] = {builtin_zig_path};
|
||||
*resolved_path = os_path_resolve(resolve_paths, 1);
|
||||
|
||||
assert(g->root_package);
|
||||
assert(g->std_package);
|
||||
g->compile_var_package = new_package(buf_ptr(g->cache_dir), builtin_zig_basename);
|
||||
g->compile_var_package = new_package(buf_ptr(&g->cache_dir), builtin_zig_basename);
|
||||
g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
|
||||
g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
|
||||
g->compile_var_import = add_source_file(g, g->compile_var_package, abs_full_path, contents);
|
||||
g->compile_var_import = add_source_file(g, g->compile_var_package, resolved_path, contents);
|
||||
scan_import(g, g->compile_var_import);
|
||||
}
|
||||
|
||||
@@ -6943,17 +7248,17 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
|
||||
Buf *code_basename = buf_create_from_str(basename);
|
||||
Buf path_to_code_src = BUF_INIT;
|
||||
os_path_join(g->zig_std_special_dir, code_basename, &path_to_code_src);
|
||||
Buf *abs_full_path = buf_alloc();
|
||||
int err;
|
||||
if ((err = os_path_real(&path_to_code_src, abs_full_path))) {
|
||||
zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
|
||||
}
|
||||
|
||||
Buf *resolve_paths[] = {&path_to_code_src};
|
||||
Buf *resolved_path = buf_alloc();
|
||||
*resolved_path = os_path_resolve(resolve_paths, 1);
|
||||
Buf *import_code = buf_alloc();
|
||||
if ((err = os_fetch_file_path(abs_full_path, import_code, false))) {
|
||||
int err;
|
||||
if ((err = os_fetch_file_path(resolved_path, import_code, false))) {
|
||||
zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
|
||||
}
|
||||
|
||||
return add_source_file(g, package, abs_full_path, import_code);
|
||||
return add_source_file(g, package, resolved_path, import_code);
|
||||
}
|
||||
|
||||
static PackageTableEntry *create_bootstrap_pkg(CodeGen *g, PackageTableEntry *pkg_with_main) {
|
||||
@@ -6978,14 +7283,14 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
TypeTableEntry *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
|
||||
TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
|
||||
TypeTableEntry *fn_type = get_test_fn_type(g);
|
||||
ZigType *str_type = get_slice_type(g, u8_ptr_type);
|
||||
ZigType *fn_type = get_test_fn_type(g);
|
||||
|
||||
const char *field_names[] = { "name", "func", };
|
||||
TypeTableEntry *field_types[] = { str_type, fn_type, };
|
||||
TypeTableEntry *struct_type = get_struct_type(g, "ZigTestFn", field_names, field_types, 2);
|
||||
ZigType *field_types[] = { str_type, fn_type, };
|
||||
ZigType *struct_type = get_struct_type(g, "ZigTestFn", field_names, field_types, 2);
|
||||
|
||||
ConstExprValue *test_fn_array = create_const_vals(1);
|
||||
test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length);
|
||||
@@ -6993,7 +7298,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
|
||||
test_fn_array->data.x_array.s_none.elements = create_const_vals(g->test_fns.length);
|
||||
|
||||
for (size_t i = 0; i < g->test_fns.length; i += 1) {
|
||||
FnTableEntry *test_fn_entry = g->test_fns.at(i);
|
||||
ZigFn *test_fn_entry = g->test_fns.at(i);
|
||||
|
||||
ConstExprValue *this_val = &test_fn_array->data.x_array.s_none.elements[i];
|
||||
this_val->special = ConstValSpecialStatic;
|
||||
@@ -7031,20 +7336,18 @@ static void gen_root_source(CodeGen *g) {
|
||||
Buf *rel_full_path = buf_alloc();
|
||||
os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, rel_full_path);
|
||||
|
||||
Buf *abs_full_path = buf_alloc();
|
||||
int err;
|
||||
if ((err = os_path_real(rel_full_path, abs_full_path))) {
|
||||
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
Buf *resolved_path = buf_alloc();
|
||||
Buf *resolve_paths[] = {rel_full_path};
|
||||
*resolved_path = os_path_resolve(resolve_paths, 1);
|
||||
|
||||
Buf *source_code = buf_alloc();
|
||||
int err;
|
||||
if ((err = os_fetch_file_path(rel_full_path, source_code, true))) {
|
||||
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g->root_import = add_source_file(g, g->root_package, abs_full_path, source_code);
|
||||
g->root_import = add_source_file(g, g->root_package, resolved_path, source_code);
|
||||
|
||||
assert(g->root_out_name);
|
||||
assert(g->out_type != OutTypeUnknown);
|
||||
@@ -7129,66 +7432,66 @@ static const char *c_int_type_names[] = {
|
||||
};
|
||||
|
||||
struct GenH {
|
||||
ZigList<TypeTableEntry *> types_to_declare;
|
||||
ZigList<ZigType *> types_to_declare;
|
||||
};
|
||||
|
||||
static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry) {
|
||||
static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_entry) {
|
||||
if (type_entry->gen_h_loop_flag)
|
||||
return;
|
||||
type_entry->gen_h_loop_flag = true;
|
||||
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdPromise:
|
||||
case ZigTypeIdInvalid:
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdNamespace:
|
||||
case ZigTypeIdBlock:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdPromise:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case ZigTypeIdVoid:
|
||||
case ZigTypeIdUnreachable:
|
||||
case ZigTypeIdBool:
|
||||
case ZigTypeIdInt:
|
||||
case ZigTypeIdFloat:
|
||||
return;
|
||||
case TypeTableEntryIdOpaque:
|
||||
case ZigTypeIdOpaque:
|
||||
gen_h->types_to_declare.append(type_entry);
|
||||
return;
|
||||
case TypeTableEntryIdStruct:
|
||||
case ZigTypeIdStruct:
|
||||
for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||
TypeStructField *field = &type_entry->data.structure.fields[i];
|
||||
prepend_c_type_to_decl_list(g, gen_h, field->type_entry);
|
||||
}
|
||||
gen_h->types_to_declare.append(type_entry);
|
||||
return;
|
||||
case TypeTableEntryIdUnion:
|
||||
case ZigTypeIdUnion:
|
||||
for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
|
||||
TypeUnionField *field = &type_entry->data.unionation.fields[i];
|
||||
prepend_c_type_to_decl_list(g, gen_h, field->type_entry);
|
||||
}
|
||||
gen_h->types_to_declare.append(type_entry);
|
||||
return;
|
||||
case TypeTableEntryIdEnum:
|
||||
case ZigTypeIdEnum:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.enumeration.tag_int_type);
|
||||
gen_h->types_to_declare.append(type_entry);
|
||||
return;
|
||||
case TypeTableEntryIdPointer:
|
||||
case ZigTypeIdPointer:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.pointer.child_type);
|
||||
return;
|
||||
case TypeTableEntryIdArray:
|
||||
case ZigTypeIdArray:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
|
||||
return;
|
||||
case TypeTableEntryIdOptional:
|
||||
case ZigTypeIdOptional:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
|
||||
return;
|
||||
case TypeTableEntryIdFn:
|
||||
case ZigTypeIdFn:
|
||||
for (size_t i = 0; i < type_entry->data.fn.fn_type_id.param_count; i += 1) {
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.fn.fn_type_id.param_info[i].type);
|
||||
}
|
||||
@@ -7197,7 +7500,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
|
||||
}
|
||||
}
|
||||
|
||||
static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf *out_buf) {
|
||||
static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_buf) {
|
||||
assert(type_entry);
|
||||
|
||||
for (size_t i = 0; i < array_length(c_int_type_names); i += 1) {
|
||||
@@ -7228,17 +7531,17 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry);
|
||||
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdVoid:
|
||||
case ZigTypeIdVoid:
|
||||
buf_init_from_str(out_buf, "void");
|
||||
break;
|
||||
case TypeTableEntryIdBool:
|
||||
case ZigTypeIdBool:
|
||||
buf_init_from_str(out_buf, "bool");
|
||||
g->c_want_stdbool = true;
|
||||
break;
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case ZigTypeIdUnreachable:
|
||||
buf_init_from_str(out_buf, "__attribute__((__noreturn__)) void");
|
||||
break;
|
||||
case TypeTableEntryIdFloat:
|
||||
case ZigTypeIdFloat:
|
||||
switch (type_entry->data.floating.bit_count) {
|
||||
case 32:
|
||||
buf_init_from_str(out_buf, "float");
|
||||
@@ -7256,17 +7559,17 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
zig_unreachable();
|
||||
}
|
||||
break;
|
||||
case TypeTableEntryIdInt:
|
||||
case ZigTypeIdInt:
|
||||
g->c_want_stdint = true;
|
||||
buf_resize(out_buf, 0);
|
||||
buf_appendf(out_buf, "%sint%" PRIu32 "_t",
|
||||
type_entry->data.integral.is_signed ? "" : "u",
|
||||
type_entry->data.integral.bit_count);
|
||||
break;
|
||||
case TypeTableEntryIdPointer:
|
||||
case ZigTypeIdPointer:
|
||||
{
|
||||
Buf child_buf = BUF_INIT;
|
||||
TypeTableEntry *child_type = type_entry->data.pointer.child_type;
|
||||
ZigType *child_type = type_entry->data.pointer.child_type;
|
||||
get_c_type(g, gen_h, child_type, &child_buf);
|
||||
|
||||
const char *const_str = type_entry->data.pointer.is_const ? "const " : "";
|
||||
@@ -7274,9 +7577,9 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
buf_appendf(out_buf, "%s%s *", const_str, buf_ptr(&child_buf));
|
||||
break;
|
||||
}
|
||||
case TypeTableEntryIdOptional:
|
||||
case ZigTypeIdOptional:
|
||||
{
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
ZigType *child_type = type_entry->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
buf_init_from_str(out_buf, "bool");
|
||||
return;
|
||||
@@ -7286,28 +7589,28 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdOpaque:
|
||||
case ZigTypeIdStruct:
|
||||
case ZigTypeIdOpaque:
|
||||
{
|
||||
buf_init_from_str(out_buf, "struct ");
|
||||
buf_append_buf(out_buf, &type_entry->name);
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdUnion:
|
||||
case ZigTypeIdUnion:
|
||||
{
|
||||
buf_init_from_str(out_buf, "union ");
|
||||
buf_append_buf(out_buf, &type_entry->name);
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdEnum:
|
||||
case ZigTypeIdEnum:
|
||||
{
|
||||
buf_init_from_str(out_buf, "enum ");
|
||||
buf_append_buf(out_buf, &type_entry->name);
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdArray:
|
||||
case ZigTypeIdArray:
|
||||
{
|
||||
TypeTableEntryArray *array_data = &type_entry->data.array;
|
||||
ZigTypeArray *array_data = &type_entry->data.array;
|
||||
|
||||
Buf *child_buf = buf_alloc();
|
||||
get_c_type(g, gen_h, array_data->child_type, child_buf);
|
||||
@@ -7316,21 +7619,21 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
buf_appendf(out_buf, "%s", buf_ptr(child_buf));
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdFn:
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdFn:
|
||||
zig_panic("TODO implement get_c_type for more types");
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdPromise:
|
||||
case ZigTypeIdInvalid:
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdNamespace:
|
||||
case ZigTypeIdBlock:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdPromise:
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
@@ -7395,7 +7698,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
Buf h_buf = BUF_INIT;
|
||||
buf_resize(&h_buf, 0);
|
||||
for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
|
||||
FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i);
|
||||
ZigFn *fn_table_entry = g->fn_defs.at(fn_def_i);
|
||||
|
||||
if (fn_table_entry->export_list.length == 0)
|
||||
continue;
|
||||
@@ -7421,7 +7724,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
const char *restrict_str = param_info->is_noalias ? "restrict" : "";
|
||||
get_c_type(g, gen_h, param_info->type, ¶m_type_c);
|
||||
|
||||
if (param_info->type->id == TypeTableEntryIdArray) {
|
||||
if (param_info->type->id == ZigTypeIdArray) {
|
||||
// Arrays decay to pointers
|
||||
buf_appendf(&h_buf, "%s%s%s %s[]", comma_str, buf_ptr(¶m_type_c),
|
||||
restrict_str, buf_ptr(param_name));
|
||||
@@ -7467,32 +7770,32 @@ static void gen_h_file(CodeGen *g) {
|
||||
fprintf(out_h, "\n");
|
||||
|
||||
for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) {
|
||||
TypeTableEntry *type_entry = gen_h->types_to_declare.at(type_i);
|
||||
ZigType *type_entry = gen_h->types_to_declare.at(type_i);
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOptional:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdPromise:
|
||||
case ZigTypeIdInvalid:
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdVoid:
|
||||
case ZigTypeIdBool:
|
||||
case ZigTypeIdUnreachable:
|
||||
case ZigTypeIdInt:
|
||||
case ZigTypeIdFloat:
|
||||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdArray:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdNamespace:
|
||||
case ZigTypeIdBlock:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdOptional:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdPromise:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdEnum:
|
||||
case ZigTypeIdEnum:
|
||||
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
|
||||
fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name));
|
||||
for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) {
|
||||
@@ -7510,7 +7813,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
fprintf(out_h, "enum %s;\n", buf_ptr(&type_entry->name));
|
||||
}
|
||||
break;
|
||||
case TypeTableEntryIdStruct:
|
||||
case ZigTypeIdStruct:
|
||||
if (type_entry->data.structure.layout == ContainerLayoutExtern) {
|
||||
fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name));
|
||||
for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
|
||||
@@ -7519,7 +7822,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
Buf *type_name_buf = buf_alloc();
|
||||
get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);
|
||||
|
||||
if (struct_field->type_entry->id == TypeTableEntryIdArray) {
|
||||
if (struct_field->type_entry->id == ZigTypeIdArray) {
|
||||
fprintf(out_h, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf),
|
||||
buf_ptr(struct_field->name),
|
||||
struct_field->type_entry->data.array.len);
|
||||
@@ -7533,7 +7836,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
fprintf(out_h, "struct %s;\n", buf_ptr(&type_entry->name));
|
||||
}
|
||||
break;
|
||||
case TypeTableEntryIdUnion:
|
||||
case ZigTypeIdUnion:
|
||||
if (type_entry->data.unionation.layout == ContainerLayoutExtern) {
|
||||
fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name));
|
||||
for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) {
|
||||
@@ -7548,7 +7851,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
fprintf(out_h, "union %s;\n", buf_ptr(&type_entry->name));
|
||||
}
|
||||
break;
|
||||
case TypeTableEntryIdOpaque:
|
||||
case ZigTypeIdOpaque:
|
||||
fprintf(out_h, "struct %s;\n\n", buf_ptr(&type_entry->name));
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user