mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Fix conversion of untyped integers to pointers
This commit is contained in:
+4
-2
@@ -5,6 +5,7 @@
|
|||||||
#import "mem.odin";
|
#import "mem.odin";
|
||||||
#import "opengl.odin";
|
#import "opengl.odin";
|
||||||
#import "os.odin";
|
#import "os.odin";
|
||||||
|
#import win32 "sys/windows.odin";
|
||||||
#import "sync.odin";
|
#import "sync.odin";
|
||||||
#import "utf8.odin";
|
#import "utf8.odin";
|
||||||
|
|
||||||
@@ -16,6 +17,9 @@ main :: proc() {
|
|||||||
fmt.println("rawptr");
|
fmt.println("rawptr");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
THINGI :: 14451;
|
||||||
|
THINGF :: 14451.1;
|
||||||
|
|
||||||
a: i32;
|
a: i32;
|
||||||
b: f32;
|
b: f32;
|
||||||
c: rawptr;
|
c: rawptr;
|
||||||
@@ -35,8 +39,6 @@ main :: proc() {
|
|||||||
i := f as int;
|
i := f as int;
|
||||||
fmt.printf("f64 arg, f=%d\n", i);
|
fmt.printf("f64 arg, f=%d\n", i);
|
||||||
}
|
}
|
||||||
THINGI :: 14451;
|
|
||||||
THINGF :: 14451.1;
|
|
||||||
|
|
||||||
foo();
|
foo();
|
||||||
foo(THINGI as int);
|
foo(THINGI as int);
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
|
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
|
||||||
return win32.InterlockedAnd(a, operand);
|
return win32.InterlockedAnd(a, operand);
|
||||||
|
|
||||||
}
|
}
|
||||||
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
|
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
|
||||||
return win32.InterlockedOr(a, operand);
|
return win32.InterlockedOr(a, operand);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ BOOL :: i32;
|
|||||||
WNDPROC :: type proc(HWND, u32, WPARAM, LPARAM) -> LRESULT #cc_c;
|
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;
|
FALSE: BOOL : 0;
|
||||||
TRUE: BOOL : 1;
|
TRUE: BOOL : 1;
|
||||||
@@ -46,7 +46,7 @@ WM_KEYUP :: 0x0101;
|
|||||||
|
|
||||||
PM_REMOVE :: 1;
|
PM_REMOVE :: 1;
|
||||||
|
|
||||||
COLOR_BACKGROUND :: 1 as HBRUSH;
|
COLOR_BACKGROUND :: HBRUSH(int(1));
|
||||||
BLACK_BRUSH :: 4;
|
BLACK_BRUSH :: 4;
|
||||||
|
|
||||||
SM_CXSCREEN :: 0;
|
SM_CXSCREEN :: 0;
|
||||||
|
|||||||
+47
-3
@@ -1398,7 +1398,8 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (in_value.kind == ExactValue_Integer) {
|
if (in_value.kind == ExactValue_Integer) {
|
||||||
return true;
|
return false;
|
||||||
|
// return true;
|
||||||
}
|
}
|
||||||
if (out_value) *out_value = in_value;
|
if (out_value) *out_value = in_value;
|
||||||
}
|
}
|
||||||
@@ -1727,6 +1728,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
||||||
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
||||||
return dst->Array.count == src->Array.count;
|
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 (bt->kind == Type_Basic) {
|
||||||
if (check_representable_as_constant(c, x->value, bt, &x->value)) {
|
if (check_representable_as_constant(c, x->value, bt, &x->value)) {
|
||||||
can_convert = true;
|
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)) {
|
} 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;
|
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) {
|
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) {
|
if (check_op_expr) {
|
||||||
check_expr_base(c, operand, op_expr, NULL);
|
check_expr_base(c, operand, op_expr, NULL);
|
||||||
if (operand->mode == Addressing_Invalid) {
|
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);
|
sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type);
|
||||||
entity = sel.entity;
|
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) {
|
if (entity == NULL) {
|
||||||
gbString op_str = expr_to_string(op_expr);
|
gbString op_str = expr_to_string(op_expr);
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
|
|||||||
@@ -1718,7 +1718,10 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, Type *type, irValue *e, Selec
|
|||||||
} else if (type->kind == Type_Record) {
|
} else if (type->kind == Type_Record) {
|
||||||
type = type->Record.fields[index]->type;
|
type = type->Record.fields[index]->type;
|
||||||
e = ir_emit_struct_ep(proc, e, index);
|
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) {
|
switch (type->Basic.kind) {
|
||||||
case Basic_any: {
|
case Basic_any: {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
@@ -3351,19 +3354,31 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
case_ast_node(se, SelectorExpr, expr);
|
case_ast_node(se, SelectorExpr, expr);
|
||||||
ir_emit_comment(proc, str_lit("SelectorExpr"));
|
ir_emit_comment(proc, str_lit("SelectorExpr"));
|
||||||
AstNode *sel = unparen_expr(se->selector);
|
AstNode *sel = unparen_expr(se->selector);
|
||||||
GB_ASSERT(sel->kind == AstNode_Ident);
|
if (sel->kind == AstNode_Ident) {
|
||||||
String selector = sel->Ident.string;
|
String selector = sel->Ident.string;
|
||||||
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
||||||
|
|
||||||
if (type == t_invalid) {
|
if (type == t_invalid) {
|
||||||
// NOTE(bill): Imports
|
// NOTE(bill): Imports
|
||||||
Entity *imp = entity_of_ident(proc->module->info, se->expr);
|
Entity *imp = entity_of_ident(proc->module->info, se->expr);
|
||||||
if (imp != NULL) {
|
if (imp != NULL) {
|
||||||
GB_ASSERT(imp->kind == Entity_ImportName);
|
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 {
|
} 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);
|
GB_ASSERT(sel.entity != NULL);
|
||||||
|
|
||||||
irValue *a = ir_build_addr(proc, se->expr).addr;
|
irValue *a = ir_build_addr(proc, se->expr).addr;
|
||||||
|
|||||||
+5
-5
@@ -1854,15 +1854,15 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|||||||
case Token_Ident:
|
case Token_Ident:
|
||||||
operand = make_selector_expr(f, token, operand, parse_identifier(f));
|
operand = make_selector_expr(f, token, operand, parse_identifier(f));
|
||||||
break;
|
break;
|
||||||
case Token_Integer:
|
// case Token_Integer:
|
||||||
operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
|
// operand = make_selector_expr(f, token, operand, parse_expr(f, lhs));
|
||||||
break;
|
// break;
|
||||||
default: {
|
default:
|
||||||
syntax_error(f->curr_token, "Expected a selector");
|
syntax_error(f->curr_token, "Expected a selector");
|
||||||
next_token(f);
|
next_token(f);
|
||||||
operand = make_bad_expr(f, ast_node_token(operand), f->curr_token);
|
operand = make_bad_expr(f, ast_node_token(operand), f->curr_token);
|
||||||
// operand = make_selector_expr(f, f->curr_token, operand, NULL);
|
// operand = make_selector_expr(f, f->curr_token, operand, NULL);
|
||||||
} break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+45
@@ -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);
|
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) {
|
Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
|
||||||
GB_ASSERT(type_ != NULL);
|
GB_ASSERT(type_ != NULL);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user