Merge remote-tracking branch 'origin/master' into llvm8
This commit is contained in:
500
src/codegen.cpp
500
src/codegen.cpp
@@ -118,6 +118,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
|
||||
g->string_literals_table.init(16);
|
||||
g->type_info_cache.init(32);
|
||||
g->is_test_build = false;
|
||||
g->is_single_threaded = false;
|
||||
buf_resize(&g->global_asm, 0);
|
||||
|
||||
for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
|
||||
@@ -313,6 +314,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
|
||||
static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
|
||||
static void generate_error_name_table(CodeGen *g);
|
||||
static bool value_is_all_undef(ConstExprValue *const_val);
|
||||
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
|
||||
|
||||
static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
|
||||
unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
|
||||
@@ -461,6 +464,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
|
||||
}
|
||||
}
|
||||
|
||||
static bool cc_want_sret_attr(CallingConvention cc) {
|
||||
switch (cc) {
|
||||
case CallingConventionNaked:
|
||||
zig_unreachable();
|
||||
case CallingConventionC:
|
||||
case CallingConventionCold:
|
||||
case CallingConventionStdcall:
|
||||
return true;
|
||||
case CallingConventionAsync:
|
||||
case CallingConventionUnspecified:
|
||||
return false;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
if (fn_table_entry->llvm_value)
|
||||
return fn_table_entry->llvm_value;
|
||||
@@ -598,9 +616,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
} else if (type_is_codegen_pointer(return_type)) {
|
||||
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
|
||||
} 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, "sret");
|
||||
if (cc_want_sret_attr(cc)) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
|
||||
}
|
||||
init_gen_i = 1;
|
||||
@@ -1903,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
|
||||
}
|
||||
|
||||
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);
|
||||
LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1963,7 +1980,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
|
||||
break;
|
||||
}
|
||||
|
||||
if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
|
||||
if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector ||
|
||||
ty->id == ZigTypeIdInt // TODO investigate if we need to change this
|
||||
) {
|
||||
switch (fn_walk->id) {
|
||||
@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
|
||||
assert(variable);
|
||||
assert(variable->value_ref);
|
||||
|
||||
if (!handle_is_ptr(variable->value->type)) {
|
||||
if (!handle_is_ptr(variable->var_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);
|
||||
gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
|
||||
variable->value_ref, variable->align_bytes, false);
|
||||
}
|
||||
|
||||
if (variable->decl_node) {
|
||||
@@ -2643,6 +2660,27 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
} else {
|
||||
return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
|
||||
}
|
||||
} else if (type_entry->id == ZigTypeIdVector) {
|
||||
ZigType *elem_type = type_entry->data.vector.elem_type;
|
||||
if (elem_type->id == ZigTypeIdFloat) {
|
||||
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
|
||||
return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
|
||||
} else if (elem_type->id == ZigTypeIdPointer) {
|
||||
zig_panic("TODO codegen for pointers in vectors");
|
||||
} else if (elem_type->id == ZigTypeIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpAddWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
|
||||
} else if (want_runtime_safety) {
|
||||
zig_panic("TODO runtime safety for vector integer addition");
|
||||
} else if (elem_type->data.integral.is_signed) {
|
||||
return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
|
||||
} else {
|
||||
return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
|
||||
}
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -2961,7 +2999,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionPtrCast *instruction)
|
||||
IrInstructionPtrCastGen *instruction)
|
||||
{
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
if (!type_has_bits(wanted_type)) {
|
||||
@@ -3149,11 +3187,11 @@ 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)
|
||||
IrInstructionDeclVarGen *decl_var_instruction)
|
||||
{
|
||||
ZigVar *var = decl_var_instruction->var;
|
||||
|
||||
if (!type_has_bits(var->value->type))
|
||||
if (!type_has_bits(var->var_type))
|
||||
return nullptr;
|
||||
|
||||
if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
|
||||
@@ -3161,34 +3199,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
|
||||
IrInstruction *init_value = decl_var_instruction->init_value;
|
||||
|
||||
bool have_init_expr = false;
|
||||
|
||||
ConstExprValue *const_val = &init_value->value;
|
||||
if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
|
||||
have_init_expr = true;
|
||||
bool have_init_expr = !value_is_all_undef(&init_value->value);
|
||||
|
||||
if (have_init_expr) {
|
||||
assert(var->value->type == init_value->value.type);
|
||||
ZigType *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->var_type, false, false,
|
||||
PtrLenSingle, var->align_bytes, 0, 0);
|
||||
LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
|
||||
gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
|
||||
} else {
|
||||
bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
|
||||
if (want_safe) {
|
||||
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);
|
||||
|
||||
assert(var->align_bytes > 0);
|
||||
|
||||
// memset uninitialized memory to 0xa
|
||||
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
|
||||
LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
|
||||
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
|
||||
}
|
||||
} else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
|
||||
uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
|
||||
gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
|
||||
}
|
||||
|
||||
gen_var_debug_decl(g, var);
|
||||
@@ -3225,21 +3245,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
|
||||
}
|
||||
|
||||
static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
return true;
|
||||
case ConstArraySpecialBuf:
|
||||
return false;
|
||||
case ConstArraySpecialNone:
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static bool value_is_all_undef(ConstExprValue *const_val) {
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
return false;
|
||||
case ConstValSpecialUndef:
|
||||
return true;
|
||||
case ConstValSpecialStatic:
|
||||
if (const_val->type->id == ZigTypeIdStruct) {
|
||||
for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
|
||||
if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else if (const_val->type->id == ZigTypeIdArray) {
|
||||
return value_is_all_undef_array(const_val, const_val->type->data.array.len);
|
||||
} else if (const_val->type->id == ZigTypeIdVector) {
|
||||
return value_is_all_undef_array(const_val, const_val->type->data.vector.len);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
|
||||
assert(type_has_bits(value_type));
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
|
||||
assert(size_bytes > 0);
|
||||
assert(ptr_align_bytes > 0);
|
||||
// memset uninitialized memory to 0xaa
|
||||
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
|
||||
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
|
||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
|
||||
assert(instruction->ptr->value.type->id == ZigTypeIdPointer);
|
||||
ZigType *ptr_type = instruction->ptr->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
if (!type_has_bits(ptr_type))
|
||||
return nullptr;
|
||||
|
||||
gen_assign_raw(g, ptr, ptr_type, value);
|
||||
|
||||
bool have_init_expr = !value_is_all_undef(&instruction->value->value);
|
||||
if (have_init_expr) {
|
||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
gen_assign_raw(g, ptr, ptr_type, value);
|
||||
} else if (ir_want_runtime_safety(g, &instruction->base)) {
|
||||
gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
|
||||
ir_llvm_value(g, instruction->ptr));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
|
||||
ZigVar *var = instruction->var;
|
||||
if (type_has_bits(var->value->type)) {
|
||||
if (type_has_bits(var->var_type)) {
|
||||
assert(var->value_ref);
|
||||
return var->value_ref;
|
||||
} else {
|
||||
@@ -3553,7 +3633,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
|
||||
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");
|
||||
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
|
||||
union_type->data.unionation.gen_union_index, "");
|
||||
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
|
||||
return bitcasted_union_field_ptr;
|
||||
}
|
||||
@@ -3715,8 +3796,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
|
||||
if (child_type->zero_bits) {
|
||||
return maybe_handle;
|
||||
} else {
|
||||
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
|
||||
if (maybe_is_ptr) {
|
||||
bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
|
||||
if (is_scalar) {
|
||||
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
|
||||
} else {
|
||||
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
|
||||
@@ -3731,17 +3812,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
|
||||
return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapOptional *instruction)
|
||||
static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionOptionalUnwrapPtr *instruction)
|
||||
{
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
ZigType *ptr_type = instruction->base_ptr->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);
|
||||
LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
|
||||
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
|
||||
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
|
||||
@@ -3755,8 +3836,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
if (child_type->zero_bits) {
|
||||
return nullptr;
|
||||
} else {
|
||||
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
|
||||
if (maybe_is_ptr) {
|
||||
bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
|
||||
if (is_scalar) {
|
||||
return maybe_ptr;
|
||||
} else {
|
||||
LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
@@ -4174,7 +4255,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
|
||||
static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
|
||||
LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
|
||||
LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
|
||||
@@ -4189,18 +4270,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
if (!handle_is_ptr(maybe_type)) {
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
||||
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
|
||||
}
|
||||
|
||||
assert(instruction->tmp_ptr != nullptr);
|
||||
assert(type_has_bits(instruction->type));
|
||||
assert(type_has_bits(child_type));
|
||||
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
|
||||
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);
|
||||
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
|
||||
|
||||
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
||||
LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
|
||||
@@ -4351,6 +4432,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
assert(array_type->data.structure.is_slice);
|
||||
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
|
||||
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
|
||||
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
|
||||
|
||||
size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
assert(ptr_index != SIZE_MAX);
|
||||
@@ -4540,12 +4622,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
|
||||
return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapErrCode *instruction)
|
||||
{
|
||||
ZigType *ptr_type = instruction->err_union->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_ptr = ir_llvm_value(g, instruction->err_union);
|
||||
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
|
||||
|
||||
if (type_has_bits(payload_type)) {
|
||||
@@ -4556,7 +4640,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
|
||||
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapErrPayload *instruction)
|
||||
{
|
||||
bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
|
||||
g->errors_by_index.length > 1;
|
||||
if (!want_safety && !type_has_bits(instruction->base.value.type))
|
||||
return nullptr;
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *err_union_type = ptr_type->data.pointer.child_type;
|
||||
@@ -4568,7 +4658,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
|
||||
return err_union_handle;
|
||||
}
|
||||
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
|
||||
if (want_safety) {
|
||||
LLVMValueRef err_val;
|
||||
if (type_has_bits(payload_type)) {
|
||||
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
|
||||
@@ -4607,7 +4697,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
|
||||
}
|
||||
|
||||
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
|
||||
return payload_val;
|
||||
}
|
||||
|
||||
@@ -5109,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable,
|
||||
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionVectorToArray *instruction)
|
||||
{
|
||||
ZigType *array_type = instruction->base.value.type;
|
||||
assert(array_type->id == ZigTypeIdArray);
|
||||
assert(handle_is_ptr(array_type));
|
||||
assert(instruction->tmp_ptr);
|
||||
LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
|
||||
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
|
||||
LLVMPointerType(instruction->vector->value.type->type_ref, 0), "");
|
||||
gen_store_untyped(g, vector, casted_ptr, 0, false);
|
||||
return instruction->tmp_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionArrayToVector *instruction)
|
||||
{
|
||||
ZigType *vector_type = instruction->base.value.type;
|
||||
assert(vector_type->id == ZigTypeIdVector);
|
||||
assert(!handle_is_ptr(vector_type));
|
||||
LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
|
||||
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
|
||||
LLVMPointerType(vector_type->type_ref, 0), "");
|
||||
return gen_load_untyped(g, casted_ptr, 0, false, "");
|
||||
}
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
@@ -5148,6 +5264,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdCUndef:
|
||||
case IrInstructionIdEmbedFile:
|
||||
case IrInstructionIdIntType:
|
||||
case IrInstructionIdVectorType:
|
||||
case IrInstructionIdMemberCount:
|
||||
case IrInstructionIdMemberType:
|
||||
case IrInstructionIdMemberName:
|
||||
@@ -5184,12 +5301,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdToBytes:
|
||||
case IrInstructionIdEnumToInt:
|
||||
case IrInstructionIdCheckRuntimeScope:
|
||||
case IrInstructionIdDeclVarSrc:
|
||||
case IrInstructionIdPtrCastSrc:
|
||||
case IrInstructionIdCmpxchgSrc:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdDeclVarGen:
|
||||
return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
case IrInstructionIdDeclVar:
|
||||
return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
|
||||
case IrInstructionIdBinOp:
|
||||
return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
|
||||
case IrInstructionIdCast:
|
||||
@@ -5220,8 +5340,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
|
||||
case IrInstructionIdTestNonNull:
|
||||
return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
|
||||
case IrInstructionIdOptionalUnwrapPtr:
|
||||
return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
|
||||
case IrInstructionIdClz:
|
||||
return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
|
||||
case IrInstructionIdCtz:
|
||||
@@ -5236,8 +5356,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
|
||||
case IrInstructionIdErrName:
|
||||
return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
|
||||
case IrInstructionIdCmpxchg:
|
||||
return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);
|
||||
case IrInstructionIdCmpxchgGen:
|
||||
return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
|
||||
case IrInstructionIdFence:
|
||||
return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
|
||||
case IrInstructionIdTruncate:
|
||||
@@ -5278,8 +5398,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
|
||||
case IrInstructionIdUnionInit:
|
||||
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
|
||||
case IrInstructionIdPtrCast:
|
||||
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
|
||||
case IrInstructionIdPtrCastGen:
|
||||
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
|
||||
case IrInstructionIdBitCast:
|
||||
return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
|
||||
case IrInstructionIdWidenOrShorten:
|
||||
@@ -5350,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
|
||||
case IrInstructionIdBitReverse:
|
||||
return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
|
||||
case IrInstructionIdArrayToVector:
|
||||
return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
|
||||
case IrInstructionIdVectorToArray:
|
||||
return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -5377,6 +5501,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
|
||||
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
|
||||
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
|
||||
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
|
||||
static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
|
||||
static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
|
||||
static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
|
||||
|
||||
static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
|
||||
switch (parent->id) {
|
||||
@@ -5387,6 +5514,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
|
||||
case ConstParentIdStruct:
|
||||
return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
|
||||
parent->data.p_struct.field_index);
|
||||
case ConstParentIdErrUnionCode:
|
||||
return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
|
||||
case ConstParentIdErrUnionPayload:
|
||||
return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
|
||||
case ConstParentIdOptionalPayload:
|
||||
return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
|
||||
case ConstParentIdArray:
|
||||
return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
|
||||
parent->data.p_array.elem_index);
|
||||
@@ -5402,7 +5535,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
|
||||
|
||||
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
|
||||
expand_undef_array(g, array_const_val);
|
||||
ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;
|
||||
ConstParent *parent = &array_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
|
||||
|
||||
LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
|
||||
@@ -5427,7 +5560,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
|
||||
ConstParent *parent = &struct_const_val->data.x_struct.parent;
|
||||
ConstParent *parent = &struct_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
@@ -5438,8 +5571,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
|
||||
ConstParent *parent = &err_union_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, err_union_err_index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
|
||||
ConstParent *parent = &err_union_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, err_union_payload_index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
|
||||
ConstParent *parent = &optional_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, maybe_child_index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
|
||||
ConstParent *parent = &union_const_val->data.x_union.parent;
|
||||
ConstParent *parent = &union_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
@@ -5509,6 +5678,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
}
|
||||
case ZigTypeIdArray:
|
||||
zig_panic("TODO bit pack an array");
|
||||
case ZigTypeIdVector:
|
||||
zig_panic("TODO bit pack a vector");
|
||||
case ZigTypeIdUnion:
|
||||
zig_panic("TODO bit pack a union");
|
||||
case ZigTypeIdStruct:
|
||||
@@ -5609,6 +5780,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialBaseErrorUnionCode:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
|
||||
assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
|
||||
if (err_union_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
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, "");
|
||||
return const_val->global_refs->llvm_value;
|
||||
}
|
||||
LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
|
||||
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
|
||||
const_val->global_refs->llvm_value = ptr_val;
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialBaseErrorUnionPayload:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
|
||||
assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
|
||||
if (err_union_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
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, "");
|
||||
return const_val->global_refs->llvm_value;
|
||||
}
|
||||
LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
|
||||
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
|
||||
const_val->global_refs->llvm_value = ptr_val;
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialBaseOptionalPayload:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
|
||||
assert(optional_const_val->type->id == ZigTypeIdOptional);
|
||||
if (optional_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
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, "");
|
||||
return const_val->global_refs->llvm_value;
|
||||
}
|
||||
LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
|
||||
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
|
||||
const_val->global_refs->llvm_value = ptr_val;
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialHardCodedAddr:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
@@ -5621,10 +5849,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
}
|
||||
case ConstPtrSpecialFunction:
|
||||
return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
|
||||
case ConstPtrSpecialNull:
|
||||
return LLVMConstNull(const_val->type->type_ref);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
|
||||
uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
|
||||
return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
|
||||
Error err;
|
||||
|
||||
@@ -5644,9 +5879,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
case ZigTypeIdInt:
|
||||
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
|
||||
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);
|
||||
return gen_const_val_err_set(g, const_val, name);
|
||||
case ZigTypeIdFloat:
|
||||
switch (type_entry->data.floating.bit_count) {
|
||||
case 16:
|
||||
@@ -5680,6 +5913,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
|
||||
} else if (type_is_codegen_pointer(child_type)) {
|
||||
return gen_const_val_ptr(g, const_val, name);
|
||||
} else if (child_type->id == ZigTypeIdErrorSet) {
|
||||
return gen_const_val_err_set(g, const_val, name);
|
||||
} else {
|
||||
LLVMValueRef child_val;
|
||||
LLVMValueRef maybe_val;
|
||||
@@ -5816,7 +6051,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
case ZigTypeIdVector: {
|
||||
uint32_t len = type_entry->data.vector.len;
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
return LLVMGetUndef(type_entry->type_ref);
|
||||
case ConstArraySpecialNone: {
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
|
||||
values[i] = gen_const_val(g, elem_value, "");
|
||||
}
|
||||
return LLVMConstVector(values, len);
|
||||
}
|
||||
case ConstArraySpecialBuf: {
|
||||
Buf *buf = const_val->data.x_array.data.s_buf;
|
||||
assert(buf_len(buf) == len);
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false);
|
||||
}
|
||||
return LLVMConstVector(values, len);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
case ZigTypeIdUnion:
|
||||
{
|
||||
LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
|
||||
@@ -5914,7 +6175,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
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;
|
||||
ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
|
||||
uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
|
||||
return LLVMConstInt(g->err_tag_type->type_ref, value, false);
|
||||
} else if (!type_has_bits(err_set_type)) {
|
||||
assert(type_has_bits(payload_type));
|
||||
@@ -5923,8 +6185,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
LLVMValueRef err_tag_value;
|
||||
LLVMValueRef err_payload_value;
|
||||
bool make_unnamed_struct;
|
||||
if (const_val->data.x_err_union.err) {
|
||||
err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
|
||||
ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
|
||||
if (err_set != nullptr) {
|
||||
err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
|
||||
err_payload_value = LLVMConstNull(payload_type->type_ref);
|
||||
make_unnamed_struct = false;
|
||||
} else {
|
||||
@@ -6130,10 +6393,13 @@ static void do_code_gen(CodeGen *g) {
|
||||
TldVar *tld_var = g->global_vars.at(i);
|
||||
ZigVar *var = tld_var->var;
|
||||
|
||||
if (var->value->type->id == ZigTypeIdComptimeFloat) {
|
||||
if (var->var_type->id == ZigTypeIdComptimeFloat) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
ConstExprValue *const_val = var->const_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (const_val->type != var->var_type) {
|
||||
zig_panic("TODO debug info for var with ptr casted value");
|
||||
}
|
||||
ZigType *var_type = g->builtin_types.entry_f128;
|
||||
ConstExprValue coerced_value;
|
||||
coerced_value.special = ConstValSpecialStatic;
|
||||
@@ -6144,10 +6410,13 @@ static void do_code_gen(CodeGen *g) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var->value->type->id == ZigTypeIdComptimeInt) {
|
||||
if (var->var_type->id == ZigTypeIdComptimeInt) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
ConstExprValue *const_val = var->const_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (const_val->type != var->var_type) {
|
||||
zig_panic("TODO debug info for var with ptr casted value");
|
||||
}
|
||||
size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
|
||||
if (bits_needed < 8) {
|
||||
bits_needed = 8;
|
||||
@@ -6158,7 +6427,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!type_has_bits(var->value->type))
|
||||
if (!type_has_bits(var->var_type))
|
||||
continue;
|
||||
|
||||
assert(var->decl_node);
|
||||
@@ -6167,9 +6436,9 @@ static void do_code_gen(CodeGen *g) {
|
||||
if (var->linkage == VarLinkageExternal) {
|
||||
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
|
||||
if (existing_llvm_var) {
|
||||
global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));
|
||||
global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
|
||||
} else {
|
||||
global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));
|
||||
global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
|
||||
// TODO debug info for the extern variable
|
||||
|
||||
LLVMSetLinkage(global_value, LLVMExternalLinkage);
|
||||
@@ -6180,9 +6449,9 @@ static void do_code_gen(CodeGen *g) {
|
||||
} else {
|
||||
bool exported = (var->linkage == VarLinkageExport);
|
||||
const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
|
||||
render_const_val(g, var->value, mangled_name);
|
||||
render_const_val_global(g, var->value, mangled_name);
|
||||
global_value = var->value->global_refs->llvm_global;
|
||||
render_const_val(g, var->const_value, mangled_name);
|
||||
render_const_val_global(g, var->const_value, mangled_name);
|
||||
global_value = var->const_value->global_refs->llvm_global;
|
||||
|
||||
if (exported) {
|
||||
LLVMSetLinkage(global_value, LLVMExternalLinkage);
|
||||
@@ -6194,8 +6463,10 @@ 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 != ZigTypeIdFn) {
|
||||
gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
|
||||
// Here we use const_value->type because that's the type of the llvm global,
|
||||
// which we const ptr cast upon use to whatever it needs to be.
|
||||
if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
|
||||
gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
|
||||
}
|
||||
|
||||
LLVMSetGlobalConstant(global_value, var->gen_is_const);
|
||||
@@ -6249,6 +6520,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
|
||||
LLVMValueRef *slot;
|
||||
ZigType *slot_type = instruction->value.type;
|
||||
uint32_t alignment_bytes = 0;
|
||||
if (instruction->id == IrInstructionIdCast) {
|
||||
IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
|
||||
slot = &cast_instruction->tmp_ptr;
|
||||
@@ -6281,13 +6553,17 @@ static void do_code_gen(CodeGen *g) {
|
||||
} else if (instruction->id == IrInstructionIdErrWrapCode) {
|
||||
IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
|
||||
slot = &err_wrap_code_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdCmpxchg) {
|
||||
IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;
|
||||
} else if (instruction->id == IrInstructionIdCmpxchgGen) {
|
||||
IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
|
||||
slot = &cmpxchg_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdVectorToArray) {
|
||||
IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
|
||||
alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
|
||||
slot = &vector_to_array_instruction->tmp_ptr;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
*slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));
|
||||
*slot = build_alloca(g, slot_type, "", alignment_bytes);
|
||||
}
|
||||
|
||||
ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
|
||||
@@ -6304,12 +6580,12 @@ static void do_code_gen(CodeGen *g) {
|
||||
for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
|
||||
ZigVar *var = fn_table_entry->variable_list.at(var_i);
|
||||
|
||||
if (!type_has_bits(var->value->type)) {
|
||||
if (!type_has_bits(var->var_type)) {
|
||||
continue;
|
||||
}
|
||||
if (ir_get_var_is_comptime(var))
|
||||
continue;
|
||||
switch (type_requires_comptime(g, var->value->type)) {
|
||||
switch (type_requires_comptime(g, var->var_type)) {
|
||||
case ReqCompTimeInvalid:
|
||||
zig_unreachable();
|
||||
case ReqCompTimeYes:
|
||||
@@ -6319,11 +6595,11 @@ static void do_code_gen(CodeGen *g) {
|
||||
}
|
||||
|
||||
if (var->src_arg_index == SIZE_MAX) {
|
||||
var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
|
||||
var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
|
||||
|
||||
var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
|
||||
buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
|
||||
var->value->type->di_type, !g->strip_debug_symbols, 0);
|
||||
var->var_type->di_type, !g->strip_debug_symbols, 0);
|
||||
|
||||
} else if (is_c_abi) {
|
||||
fn_walk_var.data.vars.var = var;
|
||||
@@ -6333,16 +6609,16 @@ static void do_code_gen(CodeGen *g) {
|
||||
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)) {
|
||||
if (handle_is_ptr(var->var_type)) {
|
||||
if (gen_info->is_byval) {
|
||||
gen_type = var->value->type;
|
||||
gen_type = var->var_type;
|
||||
} else {
|
||||
gen_type = gen_info->type;
|
||||
}
|
||||
var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
|
||||
} else {
|
||||
gen_type = var->value->type;
|
||||
var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
|
||||
gen_type = var->var_type;
|
||||
var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
|
||||
}
|
||||
if (var->decl_node) {
|
||||
var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
|
||||
@@ -6742,6 +7018,7 @@ static void define_builtin_fns(CodeGen *g) {
|
||||
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
|
||||
create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
|
||||
@@ -6967,6 +7244,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
" ArgTuple: void,\n"
|
||||
" Opaque: void,\n"
|
||||
" Promise: Promise,\n"
|
||||
" Vector: Vector,\n"
|
||||
"\n\n"
|
||||
" pub const Int = struct {\n"
|
||||
" is_signed: bool,\n"
|
||||
@@ -7085,6 +7363,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
" child: ?type,\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" pub const Vector = struct {\n"
|
||||
" len: u32,\n"
|
||||
" child: type,\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" pub const Definition = struct {\n"
|
||||
" name: []const u8,\n"
|
||||
" is_pub: bool,\n"
|
||||
@@ -7153,6 +7436,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
|
||||
}
|
||||
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
|
||||
buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
|
||||
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
|
||||
buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
|
||||
buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
|
||||
@@ -7187,6 +7471,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
|
||||
cache_buf(&cache_hash, compiler_id);
|
||||
cache_int(&cache_hash, g->build_mode);
|
||||
cache_bool(&cache_hash, g->is_test_build);
|
||||
cache_bool(&cache_hash, g->is_single_threaded);
|
||||
cache_int(&cache_hash, g->zig_target.arch.arch);
|
||||
cache_int(&cache_hash, g->zig_target.arch.sub_arch);
|
||||
cache_int(&cache_hash, g->zig_target.vendor);
|
||||
@@ -7458,9 +7743,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
|
||||
ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
|
||||
this_val->special = ConstValSpecialStatic;
|
||||
this_val->type = struct_type;
|
||||
this_val->data.x_struct.parent.id = ConstParentIdArray;
|
||||
this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
|
||||
this_val->data.x_struct.parent.data.p_array.elem_index = i;
|
||||
this_val->parent.id = ConstParentIdArray;
|
||||
this_val->parent.data.p_array.array_val = test_fn_array;
|
||||
this_val->parent.data.p_array.elem_index = i;
|
||||
this_val->data.x_struct.fields = create_const_vals(2);
|
||||
|
||||
ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
|
||||
@@ -7656,6 +7941,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
|
||||
case ZigTypeIdArray:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
|
||||
return;
|
||||
case ZigTypeIdVector:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type);
|
||||
return;
|
||||
case ZigTypeIdOptional:
|
||||
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
|
||||
return;
|
||||
@@ -7787,6 +8075,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
|
||||
buf_appendf(out_buf, "%s", buf_ptr(child_buf));
|
||||
return;
|
||||
}
|
||||
case ZigTypeIdVector:
|
||||
zig_panic("TODO implement get_c_type for vector types");
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdFn:
|
||||
@@ -7952,6 +8242,7 @@ static void gen_h_file(CodeGen *g) {
|
||||
case ZigTypeIdOptional:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdPromise:
|
||||
case ZigTypeIdVector:
|
||||
zig_unreachable();
|
||||
case ZigTypeIdEnum:
|
||||
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
|
||||
@@ -8099,6 +8390,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
||||
cache_bool(ch, g->is_static);
|
||||
cache_bool(ch, g->strip_debug_symbols);
|
||||
cache_bool(ch, g->is_test_build);
|
||||
cache_bool(ch, g->is_single_threaded);
|
||||
cache_bool(ch, g->is_native_target);
|
||||
cache_bool(ch, g->linker_rdynamic);
|
||||
cache_bool(ch, g->no_rosegment_workaround);
|
||||
|
||||
Reference in New Issue
Block a user