aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-06 22:19:32 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-06 22:19:32 +0000
commit8cfae17535518cd10ebe26eb5d4539805ce81295 (patch)
tree53da6cb276bdec3f9b5ccb88eaa7d49d5388ba1b /src
parentdf78b8ad3ebd263849eee6736fd78efe017522a4 (diff)
`map` literals
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c31
-rw-r--r--src/ir.c108
-rw-r--r--src/parser.c1
3 files changed, 105 insertions, 35 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index b271a62f9..13f66d060 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -2885,14 +2885,14 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
Type *type = operand->type;
if (!is_type_pointer(type)) {
gbString str = type_to_string(type);
- error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str);
+ error_node(operand->expr, "Expected a pointer, got `%s`", str);
gb_string_free(str);
return false;
}
type = type_deref(type);
- if (!is_type_dynamic_array(type)) {
+ if (!is_type_dynamic_array(type) && !is_type_map(type)) {
gbString str = type_to_string(type);
- error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str);
+ error_node(operand->expr, "Expected a pointer to a map or dynamic array, got `%s`", str);
gb_string_free(str);
return false;
}
@@ -4750,6 +4750,31 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
}
} break;
+ case Type_Map: {
+ if (cl->elems.count == 0) {
+ break;
+ }
+ is_constant = false;
+ { // Checker values
+ for_array(i, cl->elems) {
+ AstNode *elem = cl->elems.e[i];
+ if (elem->kind != AstNode_FieldValue) {
+ error_node(elem, "Only `field = value` elements are allowed in a map literal");
+ continue;
+ }
+ ast_node(fv, FieldValue, elem);
+ check_expr_with_type_hint(c, o, fv->field, t->Map.key);
+ check_assignment(c, o, t->Map.key, str_lit("map literal"));
+ if (o->mode == Addressing_Invalid) {
+ continue;
+ }
+
+ check_expr_with_type_hint(c, o, fv->value, t->Map.value);
+ check_assignment(c, o, t->Map.value, str_lit("map literal"));
+ }
+ }
+ } break;
+
default: {
gbString str = type_to_string(type);
error_node(node, "Invalid compound literal type `%s`", str);
diff --git a/src/ir.c b/src/ir.c
index 7d04a0dd4..c7d97fd15 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -1386,6 +1386,10 @@ void ir_emit_startup_runtime(irProcedure *proc) {
ir_emit(proc, ir_alloc_instr(proc, irInstr_StartupRuntime));
}
+irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) {
+ return ir_emit(proc, ir_make_instr_conv(proc, irConv_bitcast, data, ir_type(data), type));
+}
+
irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index);
irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irValue *right);
@@ -1419,15 +1423,26 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type)
return ir_emit_load(proc, h);
}
-irValue *ir_gen_map_key(irProcedure *proc, irValue *key) {
+irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
irValue *v = ir_add_local_generated(proc, t_map_key);
Type *t = base_type(ir_type(key));
+ key = ir_emit_conv(proc, key, key_type);
if (is_type_integer(t)) {
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, key, t_u64));
} else if (is_type_pointer(t)) {
irValue *p = ir_emit_conv(proc, key, t_uint);
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, p, t_u64));
- } else {
+ } else if (is_type_float(t)) {
+ irValue *bits = NULL;
+ i64 size = type_size_of(proc->module->sizes, proc->module->allocator, t);
+ switch (8*size) {
+ case 32: bits = ir_emit_bitcast(proc, key, t_u32); break;
+ case 64: bits = ir_emit_bitcast(proc, key, t_u64); break;
+ default: GB_PANIC("Unhandled float size: %lld bits", size); break;
+ }
+
+ ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, bits, t_u64));
+ } else if (is_type_string(t)) {
irValue *str = ir_emit_conv(proc, key, t_string);
irValue *hashed_str = NULL;
@@ -1443,6 +1458,8 @@ irValue *ir_gen_map_key(irProcedure *proc, irValue *key) {
}
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), hashed_str);
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), str);
+ } else {
+ GB_PANIC("Unhandled map key type");
}
return ir_emit_load(proc, v);
@@ -1478,37 +1495,35 @@ Type *ir_addr_type(irAddr addr) {
return type_deref(t);
}
+irValue *ir_insert_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type,
+ irValue *map_key, irValue *map_value) {
+ map_type = base_type(map_type);
+
+ irValue *h = ir_gen_map_header(proc, addr, map_type);
+ irValue *key = ir_gen_map_key(proc, map_key, map_type->Map.key);
+ irValue *v = ir_emit_conv(proc, map_value, map_type->Map.value);
+ irValue *ptr = ir_address_from_load_or_generate_local(proc, v);
+ ptr = ir_emit_conv(proc, ptr, t_rawptr);
+
+ irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 3);
+ args[0] = h;
+ args[1] = key;
+ args[2] = ptr;
+
+ return ir_emit_global_call(proc, "__dynamic_map_set", args, 3);
+}
+
irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) {
if (addr.addr == NULL) {
return NULL;
}
if (addr.kind == irAddr_Map) {
- Type *map_type = base_type(addr.map_type);
- irValue *h = ir_gen_map_header(proc, addr.addr, map_type);
- irValue *key = ir_gen_map_key(proc, addr.map_key);
- irValue *v = ir_emit_conv(proc, value, map_type->Map.value);
- irValue *ptr = ir_address_from_load_or_generate_local(proc, v);
- ptr = ir_emit_conv(proc, ptr, t_rawptr);
-
- irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 3);
- args[0] = h;
- args[1] = key;
- args[2] = ptr;
-
- return ir_emit_global_call(proc, "__dynamic_map_set", args, 3);
+ return ir_insert_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value);
}
- // if (addr.kind == irAddr_Vector) {
- // irValue *v = ir_emit_load(proc, addr.addr);
- // Type *elem_type = base_type(ir_type(v))->Vector.elem;
- // irValue *elem = ir_emit_conv(proc, value, elem_type);
- // irValue *out = ir_emit(proc, ir_make_instr_insert_element(proc, v, elem, addr.Vector.index));
- // return ir_emit_store(proc, addr.addr, out);
- // } else {
- irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
- return ir_emit_store(proc, addr.addr, v);
- // }
+ irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
+ return ir_emit_store(proc, addr.addr, v);
}
irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
@@ -1522,7 +1537,7 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
Type *map_type = base_type(addr.map_type);
irValue *v = ir_add_local_generated(proc, map_type->Map.lookup_result_type);
irValue *h = ir_gen_map_header(proc, addr.addr, map_type);
- irValue *key = ir_gen_map_key(proc, addr.map_key);
+ irValue *key = ir_gen_map_key(proc, addr.map_key, map_type->Map.key);
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
args[0] = h;
@@ -2092,9 +2107,6 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
return str_lit("");
}
-irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) {
- return ir_emit(proc, ir_make_instr_conv(proc, irConv_bitcast, data, ir_type(data), type));
-}
irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
@@ -3183,9 +3195,19 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
case BuiltinProc_clear: {
ir_emit_comment(proc, str_lit("reserve"));
- irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]);
- irValue *count_ptr = ir_emit_struct_ep(proc, array_ptr, 1);
- ir_emit_store(proc, count_ptr, v_zero);
+ irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
+ Type *t = base_type(type_deref(ir_type(ptr)));
+ if (is_type_dynamic_array(t)) {
+ irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
+ ir_emit_store(proc, count_ptr, v_zero);
+ } else if (is_type_dynamic_map(t)) {
+ irValue *ha = ir_emit_struct_ep(proc, ptr, 0);
+ irValue *ea = ir_emit_struct_ep(proc, ptr, 1);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, ha, 1), v_zero);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, ea, 1), v_zero);
+ } else {
+ GB_PANIC("TODO(bill): ir clear for `%s`", type_to_string(t));
+ }
return NULL;
} break;
@@ -4152,6 +4174,28 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
}
}
} break;
+
+ case Type_Map: {
+ if (cl->elems.count == 0) {
+ break;
+ }
+ gbAllocator a = proc->module->allocator;
+ {
+ irValue **args = gb_alloc_array(a, irValue *, 4);
+ args[0] = ir_gen_map_header(proc, v, type);
+ args[1] = ir_make_const_int(a, 2*cl->elems.count);
+ ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2);
+ }
+ for_array(field_index, cl->elems) {
+ AstNode *elem = cl->elems.e[field_index];
+ ast_node(fv, FieldValue, elem);
+
+ irValue *key = ir_build_expr(proc, fv->field);
+ irValue *value = ir_build_expr(proc, fv->value);
+ ir_insert_map_key_and_value(proc, v, type, key, value);
+ }
+ } break;
+
case Type_Array: {
if (cl->elems.count > 0) {
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
diff --git a/src/parser.c b/src/parser.c
index 652181c90..079e39c2f 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1854,6 +1854,7 @@ bool is_literal_type(AstNode *node) {
case AstNode_ArrayType:
case AstNode_VectorType:
case AstNode_StructType:
+ case AstNode_MapType:
return true;
}
return false;