Fix conversion of untyped integers to pointers

This commit is contained in:
Ginger Bill
2017-01-17 20:27:14 +00:00
parent cb59c1cf08
commit 367d307dc4
7 changed files with 129 additions and 24 deletions

View File

@@ -5,6 +5,7 @@
#import "mem.odin";
#import "opengl.odin";
#import "os.odin";
#import win32 "sys/windows.odin";
#import "sync.odin";
#import "utf8.odin";
@@ -16,6 +17,9 @@ main :: proc() {
fmt.println("rawptr");
}
THINGI :: 14451;
THINGF :: 14451.1;
a: i32;
b: f32;
c: rawptr;
@@ -35,8 +39,6 @@ main :: proc() {
i := f as int;
fmt.printf("f64 arg, f=%d\n", i);
}
THINGI :: 14451;
THINGF :: 14451.1;
foo();
foo(THINGI as int);

View File

@@ -29,7 +29,6 @@ fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
}
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
return win32.InterlockedAnd(a, operand);
}
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
return win32.InterlockedOr(a, operand);

View File

@@ -19,7 +19,7 @@ BOOL :: i32;
WNDPROC :: type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c;
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
INVALID_HANDLE_VALUE :: ~int(0) as HANDLE;
FALSE: BOOL : 0;
TRUE: BOOL : 1;
@@ -46,7 +46,7 @@ WM_KEYUP :: 0x0101;
PM_REMOVE :: 1;
COLOR_BACKGROUND :: 1 as HBRUSH;
COLOR_BACKGROUND :: HBRUSH(int(1));
BLACK_BRUSH :: 4;
SM_CXSCREEN :: 0;

View File

@@ -1398,7 +1398,8 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
return true;
}
if (in_value.kind == ExactValue_Integer) {
return true;
return false;
// return true;
}
if (out_value) *out_value = in_value;
}
@@ -1727,6 +1728,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
return true;
}
if (dst->kind == Type_Array && src->kind == Type_Array) {
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
return dst->Array.count == src->Array.count;
@@ -1868,6 +1870,8 @@ void check_conversion(Checker *c, Operand *x, Type *type) {
if (bt->kind == Type_Basic) {
if (check_representable_as_constant(c, x->value, bt, &x->value)) {
can_convert = true;
} else if (is_type_pointer(type) && check_is_castable_to(c, x, type)) {
can_convert = true;
}
}
} else if (check_is_castable_to(c, x, type)) {
@@ -2478,8 +2482,10 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
goto error;
}
if (ast_node_expect(selector, AstNode_Ident)) {
// if (selector->kind != AstNode_Ident && selector->kind != AstNode_BasicLit) {
if (selector->kind != AstNode_Ident) {
error_node(selector, "Illegal selector kind: `%.*s`", LIT(ast_node_strings[selector->kind]));
goto error;
}
if (op_expr->kind == AstNode_Ident) {
@@ -2577,6 +2583,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
}
}
}
if (check_op_expr) {
check_expr_base(c, operand, op_expr, NULL);
if (operand->mode == Addressing_Invalid) {
@@ -2589,6 +2596,43 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type);
entity = sel.entity;
}
if (entity == NULL && selector->kind == AstNode_BasicLit) {
if (is_type_struct(operand->type) || is_type_tuple(operand->type)) {
Type *type = base_type(operand->type);
Operand o = {0};
check_expr(c, &o, selector);
if (o.mode != Addressing_Constant ||
!is_type_integer(o.type)) {
error_node(op_expr, "Indexed based selectors must be a constant integer %s");
goto error;
}
i64 index = o.value.value_integer;
if (index < 0) {
error_node(o.expr, "Index %lld cannot be a negative value", index);
goto error;
}
i64 max_count = 0;
switch (type->kind) {
case Type_Record: max_count = type->Record.field_count; break;
case Type_Tuple: max_count = type->Tuple.variable_count; break;
}
if (index >= max_count) {
error_node(o.expr, "Index %lld is out of bounds range 0..<%lld", index, max_count);
goto error;
}
sel = lookup_field_from_index(heap_allocator(), type, index);
entity = sel.entity;
GB_ASSERT(entity != NULL);
} else {
error_node(op_expr, "Indexed based selectors may only be used on structs or tuples");
goto error;
}
}
if (entity == NULL) {
gbString op_str = expr_to_string(op_expr);
gbString type_str = type_to_string(operand->type);

View File

@@ -1718,7 +1718,10 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, Type *type, irValue *e, Selec
} else if (type->kind == Type_Record) {
type = type->Record.fields[index]->type;
e = ir_emit_struct_ep(proc, e, index);
} else if (type->kind == Type_Basic) {
} else if (type->kind == Type_Tuple) {
type = type->Tuple.variables[index]->type;
e = ir_emit_struct_ep(proc, e, index);
}else if (type->kind == Type_Basic) {
switch (type->Basic.kind) {
case Basic_any: {
if (index == 0) {
@@ -3351,19 +3354,31 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
case_ast_node(se, SelectorExpr, expr);
ir_emit_comment(proc, str_lit("SelectorExpr"));
AstNode *sel = unparen_expr(se->selector);
GB_ASSERT(sel->kind == AstNode_Ident);
String selector = sel->Ident.string;
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
if (sel->kind == AstNode_Ident) {
String selector = sel->Ident.string;
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
if (type == t_invalid) {
// NOTE(bill): Imports
Entity *imp = entity_of_ident(proc->module->info, se->expr);
if (imp != NULL) {
GB_ASSERT(imp->kind == Entity_ImportName);
if (type == t_invalid) {
// NOTE(bill): Imports
Entity *imp = entity_of_ident(proc->module->info, se->expr);
if (imp != NULL) {
GB_ASSERT(imp->kind == Entity_ImportName);
}
return ir_build_addr(proc, unparen_expr(se->selector));
} else {
Selection sel = lookup_field(proc->module->allocator, type, selector, false);
GB_ASSERT(sel.entity != NULL);
irValue *a = ir_build_addr(proc, se->expr).addr;
a = ir_emit_deep_field_gep(proc, type, a, sel);
return ir_make_addr(a, expr);
}
return ir_build_addr(proc, unparen_expr(se->selector));
} else {
Selection sel = lookup_field(proc->module->allocator, type, selector, false);
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
ExactValue val = type_and_value_of_expression(proc->module->info, sel)->value;
i64 index = val.value_integer;
Selection sel = lookup_field_from_index(proc->module->allocator, type, index);
GB_ASSERT(sel.entity != NULL);
irValue *a = ir_build_addr(proc, se->expr).addr;

View File

@@ -1854,15 +1854,15 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
case Token_Ident:
operand = make_selector_expr(f, token, operand, parse_identifier(f));
break;
case Token_Integer:
operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
break;
default: {
// case Token_Integer:
// operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
// break;
default:
syntax_error(f->curr_token, "Expected a selector");
next_token(f);
operand = make_bad_expr(f, ast_node_token(operand), f->curr_token);
// operand = make_selector_expr(f, f->curr_token, operand, NULL);
} break;
break;
}
} break;

View File

@@ -980,6 +980,51 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, bool is_ty
return lookup_field_with_selection(a, type_, field_name, is_type, empty_selection);
}
Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
GB_ASSERT(is_type_struct(type) || is_type_tuple(type));
type = base_type(type);
i64 max_count = 0;
switch (type->kind) {
case Type_Record: max_count = type->Record.field_count; break;
case Type_Tuple: max_count = type->Tuple.variable_count; break;
}
if (index >= max_count) {
return empty_selection;
}
switch (type->kind) {
case Type_Record:
for (isize i = 0; i < max_count; i++) {
Entity *f = type->Record.fields[i];
if (f->kind == Entity_Variable) {
if (f->Variable.field_src_index == index) {
Array_isize sel_array = {0};
array_init_count(&sel_array, a, 1);
sel_array.e[0] = i;
return make_selection(f, sel_array, false);
}
}
}
break;
case Type_Tuple:
for (isize i = 0; i < max_count; i++) {
Entity *f = type->Tuple.variables[i];
if (i == index) {
Array_isize sel_array = {0};
array_init_count(&sel_array, a, 1);
sel_array.e[0] = i;
return make_selection(f, sel_array, false);
}
}
break;
}
GB_PANIC("Illegal index");
return empty_selection;
}
Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
GB_ASSERT(type_ != NULL);