|
@@ -1,3 +1,11 @@
|
|
|
|
+gb_internal cgValue cg_flatten_value(cgProcedure *p, cgValue value) {
|
|
|
|
+ if (value.kind == cgValue_Symbol) {
|
|
|
|
+ GB_ASSERT(is_type_internally_pointer_like(value.type));
|
|
|
|
+ value = cg_value(tb_inst_get_symbol_address(p->func, value.symbol), value.type);
|
|
|
|
+ }
|
|
|
|
+ return value;
|
|
|
|
+}
|
|
|
|
+
|
|
gb_internal cgContextData *cg_push_context_onto_stack(cgProcedure *p, cgAddr ctx) {
|
|
gb_internal cgContextData *cg_push_context_onto_stack(cgProcedure *p, cgAddr ctx) {
|
|
ctx.kind = cgAddr_Context;
|
|
ctx.kind = cgAddr_Context;
|
|
cgContextData *cd = array_add_and_get(&p->context_stack);
|
|
cgContextData *cd = array_add_and_get(&p->context_stack);
|
|
@@ -43,7 +51,7 @@ gb_internal cgValue cg_find_value_from_entity(cgModule *m, Entity *e) {
|
|
return *found;
|
|
return *found;
|
|
}
|
|
}
|
|
|
|
|
|
- // GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string));
|
|
|
|
|
|
+ GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string));
|
|
return {};
|
|
return {};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -57,6 +65,10 @@ gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *exp
|
|
return {};
|
|
return {};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ cgAddr *local_found = map_get(&p->variable_map, e);
|
|
|
|
+ if (local_found) {
|
|
|
|
+ return *local_found;
|
|
|
|
+ }
|
|
|
|
|
|
cgValue v = {};
|
|
cgValue v = {};
|
|
|
|
|
|
@@ -78,7 +90,9 @@ gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *exp
|
|
|
|
|
|
|
|
|
|
if (v.node == nullptr) {
|
|
if (v.node == nullptr) {
|
|
- return cg_addr(cg_find_value_from_entity(m, e));
|
|
|
|
|
|
+ cgValue v = cg_find_value_from_entity(m, e);
|
|
|
|
+ v = cg_flatten_value(p, v);
|
|
|
|
+ return cg_addr(v);
|
|
}
|
|
}
|
|
|
|
|
|
return cg_addr(v);
|
|
return cg_addr(v);
|
|
@@ -90,6 +104,17 @@ gb_internal cgValue cg_typeid(cgModule *m, Type *t) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+gb_internal cgValue cg_correct_endianness(cgProcedure *p, cgValue value) {
|
|
|
|
+ Type *src = core_type(value.type);
|
|
|
|
+ GB_ASSERT(is_type_integer(src) || is_type_float(src));
|
|
|
|
+ if (is_type_different_to_arch_endianness(src)) {
|
|
|
|
+ GB_PANIC("TODO(bill): cg_correct_endianness");
|
|
|
|
+ // Type *platform_src_type = integer_endian_type_to_platform_type(src);
|
|
|
|
+ // value = cg_emit_byte_swap(p, value, platform_src_type);
|
|
|
|
+ }
|
|
|
|
+ return value;
|
|
|
|
+}
|
|
|
|
+
|
|
gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *type) {
|
|
gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *type) {
|
|
// TODO(bill): cg_emit_conv
|
|
// TODO(bill): cg_emit_conv
|
|
return value;
|
|
return value;
|
|
@@ -98,10 +123,7 @@ gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *type) {
|
|
gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) {
|
|
gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) {
|
|
GB_ASSERT(type_size_of(value.type) == type_size_of(type));
|
|
GB_ASSERT(type_size_of(value.type) == type_size_of(type));
|
|
|
|
|
|
- if (value.kind == cgValue_Symbol) {
|
|
|
|
- GB_ASSERT(is_type_pointer(value.type));
|
|
|
|
- value = cg_value(tb_inst_get_symbol_address(p->func, value.symbol), type);
|
|
|
|
- }
|
|
|
|
|
|
+ value = cg_flatten_value(p, value);
|
|
|
|
|
|
i64 src_align = type_align_of(value.type);
|
|
i64 src_align = type_align_of(value.type);
|
|
i64 dst_align = type_align_of(type);
|
|
i64 dst_align = type_align_of(type);
|
|
@@ -133,6 +155,217 @@ gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+gb_internal cgAddr cg_build_addr_slice_expr(cgProcedure *p, Ast *expr) {
|
|
|
|
+ ast_node(se, SliceExpr, expr);
|
|
|
|
+
|
|
|
|
+ cgValue low = cg_const_int(p, t_int, 0);
|
|
|
|
+ cgValue high = {};
|
|
|
|
+
|
|
|
|
+ if (se->low != nullptr) {
|
|
|
|
+ low = cg_correct_endianness(p, cg_build_expr(p, se->low));
|
|
|
|
+ }
|
|
|
|
+ if (se->high != nullptr) {
|
|
|
|
+ high = cg_correct_endianness(p, cg_build_expr(p, se->high));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool no_indices = se->low == nullptr && se->high == nullptr;
|
|
|
|
+ gb_unused(no_indices);
|
|
|
|
+
|
|
|
|
+ cgAddr addr = cg_build_addr(p, se->expr);
|
|
|
|
+ cgValue base = cg_addr_load(p, addr);
|
|
|
|
+ Type *type = base_type(base.type);
|
|
|
|
+
|
|
|
|
+ if (is_type_pointer(type)) {
|
|
|
|
+ type = base_type(type_deref(type));
|
|
|
|
+ addr = cg_addr(base);
|
|
|
|
+ base = cg_addr_load(p, addr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (type->kind) {
|
|
|
|
+ case Type_Slice: {
|
|
|
|
+ // Type *slice_type = type;
|
|
|
|
+ // cgValue len = cg_slice_len(p, base);
|
|
|
|
+ // if (high.value == nullptr) high = len;
|
|
|
|
+
|
|
|
|
+ // if (!no_indices) {
|
|
|
|
+ // cg_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // cgValue elem = cg_emit_ptr_offset(p, cg_slice_elem(p, base), low);
|
|
|
|
+ // cgValue new_len = cg_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+
|
|
|
|
+ // cgAddr slice = cg_add_local_generated(p, slice_type, false);
|
|
|
|
+ // cg_fill_slice(p, slice, elem, new_len);
|
|
|
|
+ // return slice;
|
|
|
|
+ GB_PANIC("cg_build_addr_slice_expr Type_Slice");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case Type_RelativeSlice:
|
|
|
|
+ GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the cg_addr_load");
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case Type_DynamicArray: {
|
|
|
|
+ // Type *elem_type = type->DynamicArray.elem;
|
|
|
|
+ // Type *slice_type = alloc_type_slice(elem_type);
|
|
|
|
+
|
|
|
|
+ // lbValue len = lb_dynamic_array_len(p, base);
|
|
|
|
+ // if (high.value == nullptr) high = len;
|
|
|
|
+
|
|
|
|
+ // if (!no_indices) {
|
|
|
|
+ // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // lbValue elem = lb_emit_ptr_offset(p, lb_dynamic_array_elem(p, base), low);
|
|
|
|
+ // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+
|
|
|
|
+ // lbAddr slice = lb_add_local_generated(p, slice_type, false);
|
|
|
|
+ // lb_fill_slice(p, slice, elem, new_len);
|
|
|
|
+ // return slice;
|
|
|
|
+ GB_PANIC("cg_build_addr_slice_expr Type_DynamicArray");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case Type_MultiPointer: {
|
|
|
|
+ // lbAddr res = lb_add_local_generated(p, type_of_expr(expr), false);
|
|
|
|
+ // if (se->high == nullptr) {
|
|
|
|
+ // lbValue offset = base;
|
|
|
|
+ // LLVMValueRef indices[1] = {low.value};
|
|
|
|
+ // offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, offset.type->MultiPointer.elem), offset.value, indices, 1, "");
|
|
|
|
+ // lb_addr_store(p, res, offset);
|
|
|
|
+ // } else {
|
|
|
|
+ // low = lb_emit_conv(p, low, t_int);
|
|
|
|
+ // high = lb_emit_conv(p, high, t_int);
|
|
|
|
+
|
|
|
|
+ // lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high);
|
|
|
|
+
|
|
|
|
+ // LLVMValueRef indices[1] = {low.value};
|
|
|
|
+ // LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base.type->MultiPointer.elem), base.value, indices, 1, "");
|
|
|
|
+ // LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, "");
|
|
|
|
+
|
|
|
|
+ // LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value;
|
|
|
|
+ // LLVMValueRef gep1 = lb_emit_struct_ep(p, res.addr, 1).value;
|
|
|
|
+ // LLVMBuildStore(p->builder, ptr, gep0);
|
|
|
|
+ // LLVMBuildStore(p->builder, len, gep1);
|
|
|
|
+ // }
|
|
|
|
+ // return res;
|
|
|
|
+ GB_PANIC("cg_build_addr_slice_expr Type_MultiPointer");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case Type_Array: {
|
|
|
|
+ // Type *slice_type = alloc_type_slice(type->Array.elem);
|
|
|
|
+ // lbValue len = lb_const_int(p->module, t_int, type->Array.count);
|
|
|
|
+
|
|
|
|
+ // if (high.value == nullptr) high = len;
|
|
|
|
+
|
|
|
|
+ // bool low_const = type_and_value_of_expr(se->low).mode == Addressing_Constant;
|
|
|
|
+ // bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant;
|
|
|
|
+
|
|
|
|
+ // if (!low_const || !high_const) {
|
|
|
|
+ // if (!no_indices) {
|
|
|
|
+ // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // lbValue elem = lb_emit_ptr_offset(p, lb_array_elem(p, lb_addr_get_ptr(p, addr)), low);
|
|
|
|
+ // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+
|
|
|
|
+ // lbAddr slice = lb_add_local_generated(p, slice_type, false);
|
|
|
|
+ // lb_fill_slice(p, slice, elem, new_len);
|
|
|
|
+ // return slice;
|
|
|
|
+ GB_PANIC("cg_build_addr_slice_expr Type_Array");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case Type_Basic: {
|
|
|
|
+ // GB_ASSERT(type == t_string);
|
|
|
|
+ // lbValue len = lb_string_len(p, base);
|
|
|
|
+ // if (high.value == nullptr) high = len;
|
|
|
|
+
|
|
|
|
+ // if (!no_indices) {
|
|
|
|
+ // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // lbValue elem = lb_emit_ptr_offset(p, lb_string_elem(p, base), low);
|
|
|
|
+ // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+
|
|
|
|
+ // lbAddr str = lb_add_local_generated(p, t_string, false);
|
|
|
|
+ // lb_fill_string(p, str, elem, new_len);
|
|
|
|
+ // return str;
|
|
|
|
+ GB_PANIC("cg_build_addr_slice_expr Type_Basic");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ case Type_Struct:
|
|
|
|
+ // if (is_type_soa_struct(type)) {
|
|
|
|
+ // lbValue len = lb_soa_struct_len(p, lb_addr_get_ptr(p, addr));
|
|
|
|
+ // if (high.value == nullptr) high = len;
|
|
|
|
+
|
|
|
|
+ // if (!no_indices) {
|
|
|
|
+ // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
|
|
|
|
+ // }
|
|
|
|
+ // #if 1
|
|
|
|
+
|
|
|
|
+ // lbAddr dst = lb_add_local_generated(p, type_of_expr(expr), true);
|
|
|
|
+ // if (type->Struct.soa_kind == StructSoa_Fixed) {
|
|
|
|
+ // i32 field_count = cast(i32)type->Struct.fields.count;
|
|
|
|
+ // for (i32 i = 0; i < field_count; i++) {
|
|
|
|
+ // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
|
|
|
|
+ // lbValue field_src = lb_emit_struct_ep(p, lb_addr_get_ptr(p, addr), i);
|
|
|
|
+ // field_src = lb_emit_array_ep(p, field_src, low);
|
|
|
|
+ // lb_emit_store(p, field_dst, field_src);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
|
|
|
|
+ // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+ // lb_emit_store(p, len_dst, new_len);
|
|
|
|
+ // } else if (type->Struct.soa_kind == StructSoa_Slice) {
|
|
|
|
+ // if (no_indices) {
|
|
|
|
+ // lb_addr_store(p, dst, base);
|
|
|
|
+ // } else {
|
|
|
|
+ // i32 field_count = cast(i32)type->Struct.fields.count - 1;
|
|
|
|
+ // for (i32 i = 0; i < field_count; i++) {
|
|
|
|
+ // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
|
|
|
|
+ // lbValue field_src = lb_emit_struct_ev(p, base, i);
|
|
|
|
+ // field_src = lb_emit_ptr_offset(p, field_src, low);
|
|
|
|
+ // lb_emit_store(p, field_dst, field_src);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
|
|
|
|
+ // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+ // lb_emit_store(p, len_dst, new_len);
|
|
|
|
+ // }
|
|
|
|
+ // } else if (type->Struct.soa_kind == StructSoa_Dynamic) {
|
|
|
|
+ // i32 field_count = cast(i32)type->Struct.fields.count - 3;
|
|
|
|
+ // for (i32 i = 0; i < field_count; i++) {
|
|
|
|
+ // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
|
|
|
|
+ // lbValue field_src = lb_emit_struct_ev(p, base, i);
|
|
|
|
+ // field_src = lb_emit_ptr_offset(p, field_src, low);
|
|
|
|
+ // lb_emit_store(p, field_dst, field_src);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
|
|
|
|
+ // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
|
|
|
|
+ // lb_emit_store(p, len_dst, new_len);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // return dst;
|
|
|
|
+ // #endif
|
|
|
|
+ // }
|
|
|
|
+ GB_PANIC("cg_build_addr_slice_expr Type_Struct");
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ GB_PANIC("Unknown slicable type");
|
|
|
|
+ return {};
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr);
|
|
gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr);
|
|
gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) {
|
|
gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) {
|
|
@@ -252,6 +485,11 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) {
|
|
return cg_value(cast(TB_Node *)nullptr, e->type);
|
|
return cg_value(cast(TB_Node *)nullptr, e->type);
|
|
}
|
|
}
|
|
GB_ASSERT(e->kind != Entity_ProcGroup);
|
|
GB_ASSERT(e->kind != Entity_ProcGroup);
|
|
|
|
+
|
|
|
|
+ cgAddr *addr = map_get(&p->variable_map, e);
|
|
|
|
+ if (addr) {
|
|
|
|
+ return cg_addr_load(p, *addr);
|
|
|
|
+ }
|
|
// return cg_find_ident(p, m, e, expr);
|
|
// return cg_find_ident(p, m, e, expr);
|
|
GB_PANIC("TODO: cg_find_ident");
|
|
GB_PANIC("TODO: cg_find_ident");
|
|
return {};
|
|
return {};
|
|
@@ -327,6 +565,17 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) {
|
|
cgValue value = cg_build_expr(p, ac->expr);
|
|
cgValue value = cg_build_expr(p, ac->expr);
|
|
return cg_emit_conv(p, value, type);
|
|
return cg_emit_conv(p, value, type);
|
|
case_end;
|
|
case_end;
|
|
|
|
+
|
|
|
|
+ case_ast_node(se, SliceExpr, expr);
|
|
|
|
+ if (is_type_slice(type_of_expr(se->expr))) {
|
|
|
|
+ // NOTE(bill): Quick optimization
|
|
|
|
+ if (se->high == nullptr &&
|
|
|
|
+ (se->low == nullptr || cg_is_expr_constant_zero(se->low))) {
|
|
|
|
+ return cg_build_expr(p, se->expr);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return cg_addr_load(p, cg_build_addr(p, expr));
|
|
|
|
+ case_end;
|
|
}
|
|
}
|
|
GB_PANIC("TODO(bill): cg_build_expr_internal %.*s", LIT(ast_strings[expr->kind]));
|
|
GB_PANIC("TODO(bill): cg_build_expr_internal %.*s", LIT(ast_strings[expr->kind]));
|
|
return {};
|
|
return {};
|
|
@@ -384,6 +633,10 @@ gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) {
|
|
Entity *e = entity_of_node(expr);
|
|
Entity *e = entity_of_node(expr);
|
|
return cg_build_addr_from_entity(p, e, expr);
|
|
return cg_build_addr_from_entity(p, e, expr);
|
|
case_end;
|
|
case_end;
|
|
|
|
+
|
|
|
|
+ case_ast_node(se, SliceExpr, expr);
|
|
|
|
+ return cg_build_addr_slice_expr(p, expr);
|
|
|
|
+ case_end;
|
|
}
|
|
}
|
|
|
|
|
|
TokenPos token_pos = ast_token(expr).pos;
|
|
TokenPos token_pos = ast_token(expr).pos;
|