Add experimental atom op tables for llvm-backend

This commit is contained in:
gingerBill
2020-05-02 18:45:57 +01:00
parent ba4363d678
commit e27f5796d6
11 changed files with 552 additions and 14 deletions

View File

@@ -1296,9 +1296,11 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
o->expr = as->lhs[i];
o->mode = Addressing_Value;
} else {
ctx->assignment_lhs_hint = unparen_expr(as->lhs[i]);
check_expr(ctx, &lhs_operands[i], as->lhs[i]);
}
}
ctx->assignment_lhs_hint = nullptr; // Reset the assignment_lhs_hint
check_assignment_arguments(ctx, lhs_operands, &rhs_operands, as->rhs);
@@ -1310,8 +1312,61 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
}
}
auto lhs_to_ignore = array_make<bool>(ctx->allocator, lhs_count);
defer (array_free(&lhs_to_ignore));
isize max = gb_min(lhs_count, rhs_count);
// NOTE(bill, 2020-05-02): This is an utter hack to get these custom atom operations working
// correctly for assignments
for (isize i = 0; i < max; i++) {
if (lhs_operands[i].mode == Addressing_AtomOpAssign) {
Operand lhs = lhs_operands[i];
Type *t = base_type(lhs.type);
GB_ASSERT(t->kind == Type_Struct);
ast_node(ie, IndexExpr, unparen_expr(lhs.expr));
TypeAtomOpTable *atom_op_table = t->Struct.atom_op_table;
GB_ASSERT(atom_op_table->op[TypeAtomOp_index_set] != nullptr);
Entity *e = atom_op_table->op[TypeAtomOp_index_set];
GB_ASSERT(e->identifier != nullptr);
Ast *proc_ident = clone_ast(e->identifier);
GB_ASSERT(ctx->file != nullptr);
TypeAndValue tv = type_and_value_of_expr(ie->expr);
Ast *expr = ie->expr;
if (is_type_pointer(tv.type)) {
// Okay
} else if (tv.mode == Addressing_Variable) {
// NOTE(bill): Hack it to take the address instead
expr = ast_unary_expr(ctx->file, {Token_And, STR_LIT("&")}, ie->expr);
} else {
continue;
}
auto args = array_make<Ast *>(heap_allocator(), 3);
args[0] = expr;
args[1] = ie->index;
args[2] = rhs_operands[i].expr;
Ast *fake_call = ast_call_expr(ctx->file, proc_ident, args, ie->open, ie->close, {});
Operand fake_operand = {};
fake_operand.expr = lhs.expr;
check_expr_base(ctx, &fake_operand, fake_call, nullptr);
AtomOpMapEntry entry = {TypeAtomOp_index_set, fake_call};
map_set(&ctx->info->atom_op_map, hash_pointer(lhs.expr), entry);
lhs_to_ignore[i] = true;
}
}
for (isize i = 0; i < max; i++) {
if (lhs_to_ignore[i]) {
continue;
}
check_assignment_variable(ctx, &lhs_operands[i], &rhs_operands[i]);
}
if (lhs_count != rhs_count) {