aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-05-02 18:45:57 +0100
committergingerBill <bill@gingerbill.org>2020-05-02 18:45:57 +0100
commite27f5796d61aa1e1dbd4b2d52e9f580fd24d3fc2 (patch)
treecfd4d3ccf48628950525cf55ae618400ae0e2543 /src/check_expr.cpp
parentba4363d67832b7f192492e1354b273296cc0c755 (diff)
Add experimental atom op tables for llvm-backend
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp79
1 files changed, 76 insertions, 3 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index af9750ee4..c998c6dc2 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -53,7 +53,7 @@ typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType);
void check_expr (CheckerContext *c, Operand *operand, Ast *expression);
void check_multi_expr (CheckerContext *c, Operand *operand, Ast *expression);
void check_multi_expr_or_type (CheckerContext *c, Operand *operand, Ast *expression);
-void check_expr_or_type (CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint = nullptr);
+void check_expr_or_type (CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint);
ExprKind check_expr_base (CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint);
void check_expr_with_type_hint (CheckerContext *c, Operand *o, Ast *e, Type *t);
Type * check_type (CheckerContext *c, Ast *expression);
@@ -8944,7 +8944,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
case_end;
case_ast_node(ue, UnaryExpr, node);
+ Ast *prev_unary_address_hint = c->unary_address_hint;
+ c->unary_address_hint = unparen_expr(node);
check_expr_base(c, o, ue->expr, type_hint);
+ c->unary_address_hint = prev_unary_address_hint;
node->viral_state_flags |= ue->expr->viral_state_flags;
if (o->mode == Addressing_Invalid) {
@@ -9070,6 +9073,47 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
return Expr_Expr;
}
+ if (t->kind == Type_Struct) {
+ TypeAtomOpTable *atom_op_table = t->Struct.atom_op_table;
+ if (atom_op_table != nullptr) {
+ if (atom_op_table->op[TypeAtomOp_index_set]) {
+ if (c->assignment_lhs_hint == node) {
+ o->mode = Addressing_AtomOpAssign;
+ o->type = o->type;
+ o->expr = node;
+ return kind;
+ }
+ }
+ if (atom_op_table->op[TypeAtomOp_index_get]) {
+ Entity *e = atom_op_table->op[TypeAtomOp_index_get];
+ if (ie->index == nullptr) {
+ gbString str = expr_to_string(o->expr);
+ error(o->expr, "Missing index for '%s'", str);
+ gb_string_free(str);
+ o->mode = Addressing_Invalid;
+ o->expr = node;
+ return kind;
+ }
+
+ GB_ASSERT(e->identifier != nullptr);
+ Ast *proc_ident = clone_ast(e->identifier);
+
+ auto args = array_make<Ast *>(heap_allocator(), 2);
+ args[0] = ie->expr;
+ args[1] = ie->index;
+
+ GB_ASSERT(c->file != nullptr);
+ Ast *fake_call = ast_call_expr(c->file, proc_ident, args, ie->open, ie->close, {});
+ check_expr_base(c, o, fake_call, type_hint);
+ AtomOpMapEntry entry = {TypeAtomOp_index_get, fake_call};
+ map_set(&c->info->atom_op_map, hash_pointer(node), entry);
+ o->expr = node;
+ return kind;
+ }
+ }
+ }
+
+
i64 max_count = -1;
bool valid = check_set_index_data(o, t, is_ptr, &max_count, o->type);
@@ -9133,8 +9177,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->value = get_constant_field_single(c, value, cast(i32)index, nullptr, nullptr);
}
}
-
- node->viral_state_flags |= ie->index->viral_state_flags;
case_end;
@@ -9191,6 +9233,37 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (is_type_soa_struct(t)) {
valid = true;
o->type = make_soa_struct_slice(c, nullptr, nullptr, t->Struct.soa_elem);
+ } else {
+ TypeAtomOpTable *atom_op_table = t->Struct.atom_op_table;
+ if (atom_op_table != nullptr && atom_op_table->op[TypeAtomOp_slice]) {
+ Entity *e = atom_op_table->op[TypeAtomOp_slice];
+ GB_ASSERT(e->identifier != nullptr);
+ Ast *proc_ident = clone_ast(e->identifier);
+
+ Ast *expr = se->expr;
+ if (o->mode == Addressing_Variable) {
+ expr = ast_unary_expr(c->file, {Token_And, STR_LIT("&")}, expr);
+ } else if (is_type_pointer(o->type)) {
+ // Okay
+ } else {
+ gbString str = expr_to_string(node);
+ error(node, "Cannot slice '%s', value is not addressable", str);
+ gb_string_free(str);
+ o->mode = Addressing_Invalid;
+ o->expr = node;
+ return kind;
+ }
+ auto args = array_make<Ast *>(heap_allocator(), 1);
+ args[0] = expr;
+
+
+ GB_ASSERT(c->file != nullptr);
+ Ast *fake_call = ast_call_expr(c->file, proc_ident, args, se->open, se->close, {});
+ check_expr_base(c, o, fake_call, type_hint);
+ AtomOpMapEntry entry = {TypeAtomOp_slice, fake_call};
+ map_set(&c->info->atom_op_map, hash_pointer(node), entry);
+ valid = true;
+ }
}
break;
}