mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-26 12:54:57 +00:00
Fix data layout issue on Windows; Remove unused loads in SSA
This commit is contained in:
@@ -1945,11 +1945,11 @@ bool abi_compat_return_by_value(gbAllocator a, ProcCallingConvention cc, Type *a
|
||||
if (abi_return_type == nullptr) {
|
||||
return false;
|
||||
}
|
||||
switch (cc) {
|
||||
case ProcCC_Odin:
|
||||
case ProcCC_Contextless:
|
||||
return false;
|
||||
}
|
||||
// switch (cc) {
|
||||
// case ProcCC_Odin:
|
||||
// case ProcCC_Contextless:
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
if (build_context.ODIN_OS == "windows") {
|
||||
|
||||
316
src/ir.cpp
316
src/ir.cpp
@@ -147,6 +147,11 @@ struct irProcedure {
|
||||
Array<irContextData> context_stack;
|
||||
|
||||
|
||||
irValue *return_ptr_hint_value;
|
||||
Ast * return_ptr_hint_ast;
|
||||
bool return_ptr_hint_used;
|
||||
|
||||
|
||||
Array<irBranchBlocks> branch_blocks;
|
||||
|
||||
i32 local_count;
|
||||
@@ -180,7 +185,7 @@ gbAllocator ir_allocator(void) {
|
||||
i64 alignment; \
|
||||
}) \
|
||||
IR_INSTR_KIND(ZeroInit, struct { irValue *address; }) \
|
||||
IR_INSTR_KIND(Store, struct { irValue *address, *value; }) \
|
||||
IR_INSTR_KIND(Store, struct { irValue *address, *value; bool is_volatile; }) \
|
||||
IR_INSTR_KIND(Load, struct { Type *type; irValue *address; }) \
|
||||
IR_INSTR_KIND(AtomicFence, struct { BuiltinProcId id; }) \
|
||||
IR_INSTR_KIND(AtomicStore, struct { \
|
||||
@@ -442,6 +447,7 @@ struct irValue {
|
||||
i32 index;
|
||||
bool index_set;
|
||||
irDebugInfo * loc;
|
||||
isize uses;
|
||||
union {
|
||||
irValueConstant Constant;
|
||||
irValueConstantSlice ConstantSlice;
|
||||
@@ -841,7 +847,7 @@ Array<irValue *> *ir_value_referrers(irValue *v) {
|
||||
void ir_module_add_value (irModule *m, Entity *e, irValue *v);
|
||||
void ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr);
|
||||
irValue *ir_emit_comment (irProcedure *p, String text);
|
||||
irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value);
|
||||
irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value, bool is_volatile=false);
|
||||
irValue *ir_emit_load (irProcedure *p, irValue *address);
|
||||
void ir_emit_jump (irProcedure *proc, irBlock *block);
|
||||
irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t);
|
||||
@@ -901,6 +907,8 @@ irValue *ir_value_global(Entity *e, irValue *value) {
|
||||
v->Global.type = alloc_type_pointer(e->type);
|
||||
v->Global.value = value;
|
||||
array_init(&v->Global.referrers, ir_allocator()); // TODO(bill): Replace heap allocator here
|
||||
|
||||
if (value) value->uses += 1;
|
||||
return v;
|
||||
}
|
||||
irValue *ir_value_param(irProcedure *parent, Entity *e, Type *abi_type) {
|
||||
@@ -988,14 +996,20 @@ irValue *ir_instr_zero_init(irProcedure *p, irValue *address) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_ZeroInit);
|
||||
irInstr *i = &v->Instr;
|
||||
i->ZeroInit.address = address;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
return v;
|
||||
}
|
||||
|
||||
irValue *ir_instr_store(irProcedure *p, irValue *address, irValue *value) {
|
||||
irValue *ir_instr_store(irProcedure *p, irValue *address, irValue *value, bool is_volatile) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_Store);
|
||||
irInstr *i = &v->Instr;
|
||||
i->Store.address = address;
|
||||
i->Store.value = value;
|
||||
i->Store.is_volatile = is_volatile;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
if (value) value->uses += 1;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1004,6 +1018,9 @@ irValue *ir_instr_load(irProcedure *p, irValue *address) {
|
||||
irInstr *i = &v->Instr;
|
||||
i->Load.address = address;
|
||||
i->Load.type = type_deref(ir_type(address));
|
||||
|
||||
if (address) address->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1020,6 +1037,10 @@ irValue *ir_instr_atomic_store(irProcedure *p, irValue *address, irValue *value,
|
||||
i->AtomicStore.address = address;
|
||||
i->AtomicStore.value = value;
|
||||
i->AtomicStore.id = id;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
if (value) value->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1029,6 +1050,9 @@ irValue *ir_instr_atomic_load(irProcedure *p, irValue *address, BuiltinProcId id
|
||||
i->AtomicLoad.address = address;
|
||||
i->AtomicLoad.type = type_deref(ir_type(address));
|
||||
i->AtomicLoad.id = id;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1039,6 +1063,10 @@ irValue *ir_instr_atomic_rmw(irProcedure *p, irValue *address, irValue *value, B
|
||||
i->AtomicRmw.address = address;
|
||||
i->AtomicRmw.value = value;
|
||||
i->AtomicRmw.id = id;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
if (value) value->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1066,6 +1094,12 @@ irValue *ir_instr_atomic_cxchg(irProcedure *p, Type *type, irValue *address, irV
|
||||
i->AtomicCxchg.old_value = old_value;
|
||||
i->AtomicCxchg.new_value = new_value;
|
||||
i->AtomicCxchg.id = id;
|
||||
|
||||
|
||||
if (address) address->uses += 1;
|
||||
if (old_value) old_value->uses += 1;
|
||||
if (new_value) new_value->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1083,6 +1117,9 @@ irValue *ir_instr_array_element_ptr(irProcedure *p, irValue *address, irValue *e
|
||||
i->ArrayElementPtr.elem_index = elem_index;
|
||||
i->ArrayElementPtr.result_type = result_type;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
if (elem_index) elem_index->uses += 1;
|
||||
|
||||
GB_ASSERT_MSG(is_type_pointer(ir_type(address)),
|
||||
"%s", type_to_string(ir_type(address)));
|
||||
return v;
|
||||
@@ -1094,6 +1131,8 @@ irValue *ir_instr_struct_element_ptr(irProcedure *p, irValue *address, i32 elem_
|
||||
i->StructElementPtr.elem_index = elem_index;
|
||||
i->StructElementPtr.result_type = result_type;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
|
||||
GB_ASSERT_MSG(is_type_pointer(ir_type(address)),
|
||||
"%s", type_to_string(ir_type(address)));
|
||||
return v;
|
||||
@@ -1104,6 +1143,10 @@ irValue *ir_instr_ptr_offset(irProcedure *p, irValue *address, irValue *offset)
|
||||
i->PtrOffset.address = address;
|
||||
i->PtrOffset.offset = offset;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
if (offset) offset->uses += 1;
|
||||
|
||||
|
||||
GB_ASSERT_MSG(is_type_pointer(ir_type(address)),
|
||||
"%s", type_to_string(ir_type(address)));
|
||||
GB_ASSERT_MSG(is_type_integer(ir_type(offset)),
|
||||
@@ -1120,6 +1163,9 @@ irValue *ir_instr_struct_extract_value(irProcedure *p, irValue *address, i32 ind
|
||||
i->StructExtractValue.address = address;
|
||||
i->StructExtractValue.index = index;
|
||||
i->StructExtractValue.result_type = result_type;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1127,6 +1173,9 @@ irValue *ir_instr_union_tag_ptr(irProcedure *p, irValue *address) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_UnionTagPtr);
|
||||
irInstr *i = &v->Instr;
|
||||
i->UnionTagPtr.address = address;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
|
||||
// i->UnionTagPtr.type = alloc_type_pointer(t_type_info_ptr);
|
||||
Type *u = type_deref(ir_type(address));
|
||||
i->UnionTagPtr.type = alloc_type_pointer(union_tag_type(u));
|
||||
@@ -1137,8 +1186,9 @@ irValue *ir_instr_union_tag_value(irProcedure *p, irValue *address) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_UnionTagValue);
|
||||
irInstr *i = &v->Instr;
|
||||
i->UnionTagValue.address = address;
|
||||
// i->UnionTagValue.type = t_type_info_ptr;
|
||||
// i->UnionTagValue.type = t_int;
|
||||
|
||||
if (address) address->uses += 1;
|
||||
|
||||
Type *u = type_deref(ir_type(address));
|
||||
i->UnionTagPtr.type = union_tag_type(u);
|
||||
return v;
|
||||
@@ -1150,6 +1200,8 @@ irValue *ir_instr_unary_op(irProcedure *p, TokenKind op, irValue *expr, Type *ty
|
||||
i->UnaryOp.op = op;
|
||||
i->UnaryOp.expr = expr;
|
||||
i->UnaryOp.type = type;
|
||||
|
||||
if (expr) expr->uses += 1;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1161,6 +1213,10 @@ irValue *ir_instr_binary_op(irProcedure *p, TokenKind op, irValue *left, irValue
|
||||
i->BinaryOp.left = left;
|
||||
i->BinaryOp.right = right;
|
||||
i->BinaryOp.type = type;
|
||||
|
||||
if (left) left->uses += 1;
|
||||
if (right) right->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1185,6 +1241,10 @@ irValue *ir_instr_phi(irProcedure *p, Array<irValue *> edges, Type *type) {
|
||||
irInstr *i = &v->Instr;
|
||||
i->Phi.edges = edges;
|
||||
i->Phi.type = type;
|
||||
|
||||
for_array(j, edges) {
|
||||
edges[j]->uses += 1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1196,6 +1256,9 @@ irValue *ir_instr_unreachable(irProcedure *p) {
|
||||
irValue *ir_instr_return(irProcedure *p, irValue *value) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_Return);
|
||||
v->Instr.Return.value = value;
|
||||
|
||||
if (value) value->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1204,6 +1267,11 @@ irValue *ir_instr_select(irProcedure *p, irValue *cond, irValue *t, irValue *f)
|
||||
v->Instr.Select.cond = cond;
|
||||
v->Instr.Select.true_value = t;
|
||||
v->Instr.Select.false_value = f;
|
||||
|
||||
if (cond) cond->uses += 1;
|
||||
if (t) t->uses += 1;
|
||||
if (f) f->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1215,6 +1283,14 @@ irValue *ir_instr_call(irProcedure *p, irValue *value, irValue *return_ptr, Arra
|
||||
v->Instr.Call.type = result_type;
|
||||
v->Instr.Call.context_ptr = context_ptr;
|
||||
v->Instr.Call.inlining = inlining;
|
||||
|
||||
if (value) value->uses += 1;
|
||||
if (return_ptr) return_ptr->uses += 1;
|
||||
for_array(i, args) {
|
||||
args[i]->uses += 1;
|
||||
}
|
||||
if (context_ptr) context_ptr->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1224,6 +1300,9 @@ irValue *ir_instr_conv(irProcedure *p, irConvKind kind, irValue *value, Type *fr
|
||||
v->Instr.Conv.value = value;
|
||||
v->Instr.Conv.from = from;
|
||||
v->Instr.Conv.to = to;
|
||||
|
||||
if (value) value->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1239,6 +1318,9 @@ irValue *ir_instr_debug_declare(irProcedure *p, Ast *expr, Entity *entity, bool
|
||||
v->Instr.DebugDeclare.entity = entity;
|
||||
v->Instr.DebugDeclare.is_addr = is_addr;
|
||||
v->Instr.DebugDeclare.value = value;
|
||||
|
||||
if (value) value->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -1257,6 +1339,9 @@ irValue *ir_value_constant_slice(Type *type, irValue *backing_array, i64 count)
|
||||
v->ConstantSlice.type = type;
|
||||
v->ConstantSlice.backing_array = backing_array;
|
||||
v->ConstantSlice.count = count;
|
||||
|
||||
if (backing_array) backing_array->uses += 1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -2683,7 +2768,7 @@ irValue *ir_emit_runtime_call(irProcedure *proc, char
|
||||
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, Ast *expr = nullptr, ProcInlining inlining = ProcInlining_none);
|
||||
|
||||
|
||||
irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
|
||||
irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is_volatile) {
|
||||
Type *a = type_deref(ir_type(address));
|
||||
|
||||
if (is_type_boolean(a)) {
|
||||
@@ -2691,11 +2776,15 @@ irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
|
||||
value = ir_emit_conv(p, value, a);
|
||||
}
|
||||
|
||||
address->uses += 1;
|
||||
value->uses += 1;
|
||||
|
||||
|
||||
Type *b = ir_type(value);
|
||||
if (!is_type_untyped(b)) {
|
||||
GB_ASSERT_MSG(are_types_identical(core_type(a), core_type(b)), "%s %s", type_to_string(a), type_to_string(b));
|
||||
}
|
||||
return ir_emit(p, ir_instr_store(p, address, value));
|
||||
return ir_emit(p, ir_instr_store(p, address, value, is_volatile));
|
||||
}
|
||||
irValue *ir_emit_load(irProcedure *p, irValue *address) {
|
||||
GB_ASSERT(address != nullptr);
|
||||
@@ -2703,9 +2792,14 @@ irValue *ir_emit_load(irProcedure *p, irValue *address) {
|
||||
// if (is_type_boolean(t)) {
|
||||
// return ir_emit(p, ir_instr_load_bool(p, address));
|
||||
// }
|
||||
address->uses += 1;
|
||||
return ir_emit(p, ir_instr_load(p, address));
|
||||
}
|
||||
irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) {
|
||||
cond->uses += 1;
|
||||
t->uses += 1;
|
||||
f->uses += 1;
|
||||
|
||||
return ir_emit(p, ir_instr_select(p, cond, t, f));
|
||||
}
|
||||
|
||||
@@ -2741,6 +2835,9 @@ void ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) {
|
||||
gbAllocator a = ir_allocator();
|
||||
Type *t = type_deref(ir_type(address));
|
||||
isize sz = type_size_of(t);
|
||||
|
||||
address->uses += 1;
|
||||
|
||||
if (!(gb_is_power_of_two(sz) && sz <= build_context.max_align)) {
|
||||
// TODO(bill): Is this a good idea?
|
||||
auto args = array_make<irValue *>(a, 2);
|
||||
@@ -2748,7 +2845,9 @@ void ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) {
|
||||
args[1] = ir_const_int(type_size_of(t));
|
||||
AstPackage *pkg = get_core_package(p->module->info, str_lit("mem"));
|
||||
if (p->entity != nullptr && p->entity->token.string != "zero" && p->entity->pkg != pkg) {
|
||||
irValue *v = ir_emit_package_call(p, "mem", "zero", args, expr, ProcInlining_no_inline);
|
||||
ir_emit_comment(p, str_lit("ZeroInit"));
|
||||
irValue *v = ir_emit_package_call(p, "mem", "zero", args, expr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ir_emit(p, ir_instr_zero_init(p, address));
|
||||
@@ -2779,10 +2878,14 @@ irValue *ir_copy_value_to_ptr(irProcedure *proc, irValue *val, Type *new_type, i
|
||||
irValue *ptr = ir_add_local_generated(proc, new_type, false);
|
||||
ptr->Instr.Local.alignment = alignment;
|
||||
ir_emit_store(proc, ptr, val);
|
||||
|
||||
val->uses += 1;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) {
|
||||
data->uses += 1;
|
||||
return ir_emit(proc, ir_instr_conv(proc, irConv_bitcast, data, ir_type(data), type));
|
||||
}
|
||||
|
||||
@@ -2843,7 +2946,7 @@ Array<irValue *> ir_value_to_array(irProcedure *p, irValue *value) {
|
||||
}
|
||||
|
||||
|
||||
irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args, ProcInlining inlining = ProcInlining_none) {
|
||||
irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args, ProcInlining inlining = ProcInlining_none, bool use_return_ptr_hint = false) {
|
||||
Type *pt = base_type(ir_type(value));
|
||||
GB_ASSERT(pt->kind == Type_Proc);
|
||||
Type *results = pt->Proc.results;
|
||||
@@ -2894,7 +2997,17 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args, Pro
|
||||
Type *abi_rt = pt->Proc.abi_compat_result_type;
|
||||
Type *rt = reduce_tuple_to_single_type(results);
|
||||
if (pt->Proc.return_by_pointer) {
|
||||
irValue *return_ptr = ir_add_local_generated(p, rt, true);
|
||||
irValue *return_ptr = nullptr;
|
||||
if (use_return_ptr_hint) {
|
||||
if (are_types_identical(type_deref(ir_type(p->return_ptr_hint_value)), rt)) {
|
||||
return_ptr = p->return_ptr_hint_value;
|
||||
p->return_ptr_hint_used = true;
|
||||
return_ptr->uses += 1;
|
||||
}
|
||||
}
|
||||
if (return_ptr == nullptr) {
|
||||
return_ptr = ir_add_local_generated(p, rt, true);
|
||||
}
|
||||
GB_ASSERT(is_type_pointer(ir_type(return_ptr)));
|
||||
ir_emit(p, ir_instr_call(p, value, return_ptr, args, nullptr, context_ptr, inlining));
|
||||
result = ir_emit_load(p, return_ptr);
|
||||
@@ -3245,7 +3358,7 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
}
|
||||
irValue *ptr = ir_emit_conv(proc, bytes, alloc_type_pointer(int_type));
|
||||
v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type);
|
||||
ir_emit_store(proc, ptr, v);
|
||||
ir_emit_store(proc, ptr, v, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3257,7 +3370,7 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
irValue *v = ir_emit_conv(proc, value, t_u8);
|
||||
v = ir_emit_arith(proc, Token_Shl, v, shift_amount, int_type);
|
||||
v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, bytes), v, int_type);
|
||||
ir_emit_store(proc, bytes, v);
|
||||
ir_emit_store(proc, bytes, v, true);
|
||||
|
||||
}
|
||||
|
||||
@@ -3267,7 +3380,7 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
irValue *ptr = ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), alloc_type_pointer(int_type));
|
||||
irValue *v = ir_emit_arith(proc, Token_Shr, value, shift_amount, int_type);
|
||||
v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type);
|
||||
ir_emit_store(proc, ptr, v);
|
||||
ir_emit_store(proc, ptr, v, true);
|
||||
return;
|
||||
}
|
||||
} else if (addr.kind == irAddr_Context) {
|
||||
@@ -6492,7 +6605,8 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return ir_emit_call(proc, value, args, ce->inlining);
|
||||
|
||||
return ir_emit_call(proc, value, args, ce->inlining, proc->return_ptr_hint_ast == expr);
|
||||
}
|
||||
|
||||
isize arg_index = 0;
|
||||
@@ -6686,7 +6800,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
|
||||
}
|
||||
|
||||
auto call_args = array_slice(args, 0, final_count);
|
||||
return ir_emit_call(proc, value, call_args, ce->inlining);
|
||||
return ir_emit_call(proc, value, call_args, ce->inlining, proc->return_ptr_hint_ast == expr);
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, SliceExpr, expr);
|
||||
@@ -6756,6 +6870,14 @@ irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, Ast *expr) {
|
||||
return ir_addr(v);
|
||||
}
|
||||
|
||||
|
||||
struct irCompoundLitElemTempData {
|
||||
Ast *expr;
|
||||
irValue *value;
|
||||
i32 elem_index;
|
||||
irValue *gep;
|
||||
};
|
||||
|
||||
irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
||||
switch (expr->kind) {
|
||||
case_ast_node(i, Implicit, expr);
|
||||
@@ -7225,6 +7347,103 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Array: {
|
||||
if (cl->elems.count > 0) {
|
||||
// ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
||||
|
||||
auto temp_data = array_make<irCompoundLitElemTempData>(heap_allocator(), 0, cl->elems.count);
|
||||
defer (array_free(&temp_data));
|
||||
|
||||
// NOTE(bill): Separate value, gep, store into their own chunks
|
||||
for_array(i, cl->elems) {
|
||||
Ast *elem = cl->elems[i];
|
||||
if (ir_is_elem_const(proc->module, elem, et)) {
|
||||
continue;
|
||||
}
|
||||
irCompoundLitElemTempData data = {};
|
||||
data.expr = elem;
|
||||
data.elem_index = cast(i32)i;
|
||||
array_add(&temp_data, data);
|
||||
}
|
||||
|
||||
for_array(i, temp_data) {
|
||||
temp_data[i].gep = ir_emit_array_epi(proc, v, temp_data[i].elem_index);
|
||||
}
|
||||
|
||||
for_array(i, temp_data) {
|
||||
auto return_ptr_hint_ast = proc->return_ptr_hint_ast;
|
||||
auto return_ptr_hint_value = proc->return_ptr_hint_value;
|
||||
auto return_ptr_hint_used = proc->return_ptr_hint_used;
|
||||
defer (proc->return_ptr_hint_ast = return_ptr_hint_ast);
|
||||
defer (proc->return_ptr_hint_value = return_ptr_hint_value);
|
||||
defer (proc->return_ptr_hint_used = return_ptr_hint_used);
|
||||
|
||||
Ast *expr = temp_data[i].expr;
|
||||
|
||||
proc->return_ptr_hint_value = temp_data[i].gep;
|
||||
proc->return_ptr_hint_ast = unparen_expr(expr);
|
||||
|
||||
irValue *field_expr = ir_build_expr(proc, expr);
|
||||
Type *t = ir_type(field_expr);
|
||||
GB_ASSERT(t->kind != Type_Tuple);
|
||||
irValue *ev = ir_emit_conv(proc, field_expr, et);
|
||||
|
||||
if (!proc->return_ptr_hint_used) {
|
||||
temp_data[i].value = ev;
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, temp_data) {
|
||||
if (temp_data[i].value != nullptr) {
|
||||
ir_emit_store(proc, temp_data[i].gep, temp_data[i].value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type_Slice: {
|
||||
if (cl->elems.count > 0) {
|
||||
Type *elem_type = bt->Slice.elem;
|
||||
Type *elem_ptr_type = alloc_type_pointer(elem_type);
|
||||
Type *elem_ptr_ptr_type = alloc_type_pointer(elem_ptr_type);
|
||||
irValue *slice = ir_add_module_constant(proc->module, type, exact_value_compound(expr));
|
||||
GB_ASSERT(slice->kind == irValue_ConstantSlice);
|
||||
|
||||
irValue *data = ir_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
|
||||
|
||||
auto temp_data = array_make<irCompoundLitElemTempData>(heap_allocator(), 0, cl->elems.count);
|
||||
defer (array_free(&temp_data));
|
||||
|
||||
for_array(i, cl->elems) {
|
||||
Ast *elem = cl->elems[i];
|
||||
if (ir_is_elem_const(proc->module, elem, et)) {
|
||||
continue;
|
||||
}
|
||||
irValue *field_expr = ir_build_expr(proc, elem);
|
||||
Type *t = ir_type(field_expr);
|
||||
GB_ASSERT(t->kind != Type_Tuple);
|
||||
irValue *ev = ir_emit_conv(proc, field_expr, et);
|
||||
|
||||
irCompoundLitElemTempData data = {};
|
||||
data.value = ev;
|
||||
data.elem_index = cast(i32)i;
|
||||
array_add(&temp_data, data);
|
||||
}
|
||||
|
||||
for_array(i, temp_data) {
|
||||
temp_data[i].gep = ir_emit_ptr_offset(proc, data, ir_const_int(temp_data[i].elem_index));
|
||||
}
|
||||
|
||||
for_array(i, temp_data) {
|
||||
ir_emit_store(proc, temp_data[i].gep, temp_data[i].value);
|
||||
}
|
||||
|
||||
irValue *count = ir_const_int(slice->ConstantSlice.count);
|
||||
ir_fill_slice(proc, v, data, count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_DynamicArray: {
|
||||
if (cl->elems.count == 0) {
|
||||
break;
|
||||
@@ -7266,54 +7485,6 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Array: {
|
||||
if (cl->elems.count > 0) {
|
||||
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
||||
for_array(i, cl->elems) {
|
||||
Ast *elem = cl->elems[i];
|
||||
if (ir_is_elem_const(proc->module, elem, et)) {
|
||||
continue;
|
||||
}
|
||||
irValue *field_expr = ir_build_expr(proc, elem);
|
||||
Type *t = ir_type(field_expr);
|
||||
GB_ASSERT(t->kind != Type_Tuple);
|
||||
irValue *ev = ir_emit_conv(proc, field_expr, et);
|
||||
irValue *gep = ir_emit_array_epi(proc, v, cast(i32)i);
|
||||
ir_emit_store(proc, gep, ev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type_Slice: {
|
||||
if (cl->elems.count > 0) {
|
||||
Type *elem_type = bt->Slice.elem;
|
||||
Type *elem_ptr_type = alloc_type_pointer(elem_type);
|
||||
Type *elem_ptr_ptr_type = alloc_type_pointer(elem_ptr_type);
|
||||
irValue *slice = ir_add_module_constant(proc->module, type, exact_value_compound(expr));
|
||||
GB_ASSERT(slice->kind == irValue_ConstantSlice);
|
||||
|
||||
irValue *data = ir_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
|
||||
|
||||
for_array(i, cl->elems) {
|
||||
Ast *elem = cl->elems[i];
|
||||
if (ir_is_elem_const(proc->module, elem, et)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
irValue *field_expr = ir_build_expr(proc, elem);
|
||||
Type *t = ir_type(field_expr);
|
||||
GB_ASSERT(t->kind != Type_Tuple);
|
||||
irValue *ev = ir_emit_conv(proc, field_expr, elem_type);
|
||||
irValue *offset = ir_emit_ptr_offset(proc, data, ir_const_int(i));
|
||||
ir_emit_store(proc, offset, ev);
|
||||
}
|
||||
|
||||
irValue *count = ir_const_int(slice->ConstantSlice.count);
|
||||
ir_fill_slice(proc, v, data, count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Type_Basic: {
|
||||
GB_ASSERT(is_type_any(bt));
|
||||
if (cl->elems.count > 0) {
|
||||
@@ -8908,6 +9079,23 @@ void ir_begin_procedure_body(irProcedure *proc) {
|
||||
}
|
||||
|
||||
|
||||
void ir_remove_dead_instr(irProcedure *proc) {
|
||||
for_array(i, proc->blocks) {
|
||||
irBlock *b = proc->blocks[i];
|
||||
b->index = cast(i32)i;
|
||||
for (isize j = 0; j < b->instrs.count; j += 1) {
|
||||
irValue *value = b->instrs[j];
|
||||
GB_ASSERT_MSG(value->kind == irValue_Instr, "%.*s", LIT(proc->name));
|
||||
irInstr *instr = &value->Instr;
|
||||
if (instr->kind == irInstr_Load && value->uses == 0) {
|
||||
gb_memmove(b->instrs.data+j, b->instrs.data+j+1, gb_size_of(irValue *)*(b->instrs.count-j-1));
|
||||
b->instrs.count -= 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ir_end_procedure_body(irProcedure *proc) {
|
||||
if (proc->type->Proc.result_count == 0) {
|
||||
ir_emit_return(proc, nullptr);
|
||||
@@ -8923,6 +9111,8 @@ void ir_end_procedure_body(irProcedure *proc) {
|
||||
ir_emit_jump(proc, proc->entry_block);
|
||||
proc->curr_block = nullptr;
|
||||
|
||||
ir_remove_dead_instr(proc);
|
||||
|
||||
ir_number_proc_registers(proc);
|
||||
|
||||
ir_pop_debug_location(proc->module);
|
||||
|
||||
@@ -284,6 +284,7 @@ void ir_opt_build_referrers(irProcedure *proc) {
|
||||
irValue *instr = b->instrs[j];
|
||||
array_clear(&ops);
|
||||
ir_opt_add_operands(&ops, &instr->Instr);
|
||||
|
||||
for_array(k, ops) {
|
||||
irValue *op = ops[k];
|
||||
if (op == nullptr) {
|
||||
|
||||
@@ -676,7 +676,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
ir_write_str_lit(f, "* ");
|
||||
ir_print_encoded_global(f, str_array->Global.entity->token.string, false);
|
||||
ir_write_str_lit(f, ", ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_print_type(f, m, t_i32);
|
||||
ir_write_str_lit(f, " 0, i32 0)");
|
||||
} else {
|
||||
// HACK NOTE(bill): This is a hack but it works because strings are created at the very end
|
||||
@@ -689,7 +689,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
ir_write_str_lit(f, "* ");
|
||||
ir_print_encoded_global(f, str_array->Global.entity->token.string, false);
|
||||
ir_write_str_lit(f, ", ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_print_type(f, m, t_i32);
|
||||
ir_write_str_lit(f, " 0, i32 0), ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_fprintf(f, " %lld}", cast(i64)str.len);
|
||||
@@ -985,9 +985,7 @@ void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hin
|
||||
ir_print_type(f, m, at);
|
||||
ir_write_str_lit(f, "* ");
|
||||
ir_print_value(f, m, cs->backing_array, at);
|
||||
ir_write_str_lit(f, ", ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_write_str_lit(f, " 0, i32 0), ");
|
||||
ir_write_str_lit(f, ", i32 0, i32 0), ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_fprintf(f, " %lld}", cs->count);
|
||||
}
|
||||
@@ -1061,6 +1059,7 @@ void ir_print_calling_convention(irFileBuffer *f, irModule *m, ProcCallingConven
|
||||
void ir_print_context_parameter_prefix(irFileBuffer *f, irModule *m) {
|
||||
ir_print_type(f, m, t_context_ptr);
|
||||
ir_write_str_lit(f, " noalias nonnull nocapture inreg ");
|
||||
// ir_write_str_lit(f, " noalias nonnull nocapture ");
|
||||
}
|
||||
|
||||
void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
@@ -1103,6 +1102,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
|
||||
case irInstr_ZeroInit: {
|
||||
Type *type = type_deref(ir_type(instr->ZeroInit.address));
|
||||
ir_write_str_lit(f, "; ZeroInit\n\t");
|
||||
ir_write_str_lit(f, "store ");
|
||||
ir_print_type(f, m, type);
|
||||
ir_write_byte(f, ' ');
|
||||
@@ -1116,6 +1116,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
case irInstr_Store: {
|
||||
Type *type = type_deref(ir_type(instr->Store.address));
|
||||
ir_write_str_lit(f, "store ");
|
||||
if (instr->Store.is_volatile) {
|
||||
ir_write_str_lit(f, "volatile ");
|
||||
}
|
||||
ir_print_type(f, m, type);
|
||||
ir_write_byte(f, ' ');
|
||||
ir_print_value(f, m, instr->Store.value, type);
|
||||
@@ -1417,9 +1420,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_type(f, m, et);
|
||||
ir_write_byte(f, ' ');
|
||||
ir_print_value(f, m, instr->ArrayElementPtr.address, et);
|
||||
ir_write_str_lit(f, ", ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_write_str_lit(f, " 0, ");
|
||||
ir_write_str_lit(f, ", i32 0, ");
|
||||
|
||||
irValue *index =instr->ArrayElementPtr.elem_index;
|
||||
Type *t = ir_type(index);
|
||||
@@ -1447,9 +1448,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_type(f, m, et);
|
||||
ir_write_byte(f, ' ');
|
||||
ir_print_value(f, m, instr->StructElementPtr.address, et);
|
||||
ir_write_str_lit(f, ", ");
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_write_str_lit(f, " 0, ");
|
||||
ir_write_str_lit(f, ", i32 0, ");
|
||||
ir_print_type(f, m, t_i32);
|
||||
ir_fprintf(f, " %d", index);
|
||||
break;
|
||||
@@ -1779,9 +1778,10 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_write_byte(f, ' ');
|
||||
ir_print_value(f, m, call->value, call->type);
|
||||
|
||||
bool return_by_pointer = proc_type->Proc.return_by_pointer;
|
||||
|
||||
ir_write_byte(f, '(');
|
||||
if (proc_type->Proc.return_by_pointer) {
|
||||
if (return_by_pointer) {
|
||||
GB_ASSERT(call->return_ptr != nullptr);
|
||||
ir_print_type(f, m, proc_type->Proc.results);
|
||||
ir_write_str_lit(f, "* ");
|
||||
@@ -1850,7 +1850,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
}
|
||||
}
|
||||
if (proc_type->Proc.calling_convention == ProcCC_Odin) {
|
||||
if (param_index > 0) ir_write_str_lit(f, ", ");
|
||||
if (param_index > 0 || return_by_pointer) ir_write_str_lit(f, ", ");
|
||||
|
||||
ir_print_context_parameter_prefix(f, m);
|
||||
ir_print_value(f, m, call->context_ptr, t_context_ptr);
|
||||
@@ -1952,7 +1952,6 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
||||
ir_print_encoded_global(f, proc->name, ir_print_is_proc_global(m, proc));
|
||||
|
||||
ir_write_byte(f, '(');
|
||||
|
||||
if (proc_type->return_by_pointer) {
|
||||
ir_print_type(f, m, reduce_tuple_to_single_type(proc_type->results));
|
||||
ir_write_str_lit(f, "* sret noalias ");
|
||||
@@ -1993,7 +1992,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
||||
}
|
||||
}
|
||||
if (proc_type->calling_convention == ProcCC_Odin) {
|
||||
if (param_index > 0) ir_write_str_lit(f, ", ");
|
||||
if (param_index > 0 || proc_type->return_by_pointer) ir_write_str_lit(f, ", ");
|
||||
|
||||
ir_print_context_parameter_prefix(f, m);
|
||||
ir_write_str_lit(f, "%__.context_ptr");
|
||||
@@ -2098,10 +2097,6 @@ void ir_print_type_name(irFileBuffer *f, irModule *m, irValue *v) {
|
||||
ir_write_byte(f, '\n');
|
||||
}
|
||||
|
||||
void foo_bar(void) {
|
||||
|
||||
}
|
||||
|
||||
void print_llvm_ir(irGen *ir) {
|
||||
irModule *m = &ir->module;
|
||||
|
||||
@@ -2115,6 +2110,9 @@ void print_llvm_ir(irGen *ir) {
|
||||
ir_write_str_lit(f, "target triple = \"x86_64-apple-macosx10.8\"\n\n");
|
||||
} else if (build_context.ODIN_OS == "windows") {
|
||||
ir_fprintf(f, "target triple = \"x86%s-pc-windows-msvc\"\n\n", word_bits == 64 ? "_64" : "");
|
||||
if (word_bits == 64 && build_context.metrics.arch == TargetArch_amd64) {
|
||||
ir_fprintf(f, "target datalayout = \"e-m:w-i64:64-f80:128-n8:16:32:64-S128\"\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
ir_print_encoded_local(f, str_lit("..opaque"));
|
||||
|
||||
Reference in New Issue
Block a user