aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-08-31 00:52:19 +0100
committerGinger Bill <bill@gingerbill.org>2016-08-31 00:52:19 +0100
commit5399463d9d9f94a20fb6b80814318e2b154b199a (patch)
treec8508a4544f7292f00d4547fb5875aaa00e5307f /src/codegen
parentcda0234d487ab73a1c87cbdcd74e300718ca7d0a (diff)
`down_cast`
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/ssa.cpp29
1 files changed, 25 insertions, 4 deletions
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index 38a4647f1..3f02b16aa 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -1408,7 +1408,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
if (field_name.len > 0) {
// NOTE(bill): It can be casted
- Selection sel = lookup_field(sb, field_name, Addressing_Variable);
+ Selection sel = lookup_field(sb, field_name, false);
if (sel.entity != NULL) {
if (src_is_ptr) {
value = ssa_emit_load(proc, value);
@@ -1517,6 +1517,24 @@ ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
return NULL;
}
+ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
+ GB_ASSERT(is_type_pointer(ssa_type(value)));
+ gbAllocator allocator = proc->module->allocator;
+
+ // String field_name = check_down_cast_name(t, ssa_type(value));
+ String field_name = check_down_cast_name(t, type_deref(ssa_type(value)));
+ GB_ASSERT(field_name.len > 0);
+ Selection sel = lookup_field(t, field_name, false);
+ Type *t_u8_ptr = make_type_pointer(allocator, t_u8);
+ ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr);
+
+ // IMPORTANT TODO(bill): THIS ONLY DOES ONE LAY DEEP!!! FUCKING HELL THIS IS NOT WHAT I SIGNED UP FOR!
+
+ i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
+ ssaValue *offset = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(-offset_));
+ ssaValue *head = ssa_emit_ptr_offset(proc, bytes, offset);
+ return ssa_emit_conv(proc, head, t);
+}
@@ -1619,6 +1637,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case Token_transmute:
return ssa_emit_transmute(proc, ssa_build_expr(proc, be->left), tv->type);
+ case Token_down_cast:
+ return ssa_emit_down_cast(proc, ssa_build_expr(proc, be->left), tv->type);
+
default:
GB_PANIC("Invalid binary expression");
break;
@@ -1705,7 +1726,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
if (elem->kind == AstNode_FieldValue) {
ast_node(kv, FieldValue, elem);
- Selection sel = lookup_field(base_type, kv->field->Ident.token.string, Addressing_Value);
+ Selection sel = lookup_field(base_type, kv->field->Ident.token.string, false);
field_index = sel.index[0];
field_expr = ssa_build_expr(proc, kv->value);
} else {
@@ -2115,7 +2136,7 @@ ssaValue *ssa_add_using_variable(ssaProcedure *proc, Entity *e) {
p = ssa_add_using_variable(proc, parent);
}
- Selection sel = lookup_field(parent->type, name, Addressing_Variable);
+ Selection sel = lookup_field(parent->type, name, false);
GB_ASSERT(sel.entity != NULL);
ssaValue **pv = map_get(&proc->module->values, hash_pointer(parent));
ssaValue *v = NULL;
@@ -2160,7 +2181,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
case_ast_node(se, SelectorExpr, expr);
Type *type = get_base_type(type_of_expr(proc->module->info, se->expr));
- Selection sel = lookup_field(type, unparen_expr(se->selector)->Ident.token.string, Addressing_Value);
+ Selection sel = lookup_field(type, unparen_expr(se->selector)->Ident.token.string, false);
GB_ASSERT(sel.entity != NULL);
ssaValue *e = ssa_build_addr(proc, se->expr).addr;