typedef struct AstDereference AstDereference;
typedef struct AstArrayAccess AstArrayAccess;
typedef struct AstFieldAccess AstFieldAccess;
+typedef struct AstSizeOf AstSizeOf;
-typedef struct AstAssign AstAssign;
typedef struct AstReturn AstReturn;
typedef struct AstBlock AstBlock;
Ast_Kind_Dereference,
Ast_Kind_Array_Access,
Ast_Kind_Field_Access,
+ Ast_Kind_Size_Of,
Ast_Kind_If,
Ast_Kind_For,
#define AstNode_base struct AstNode_members;
struct AstNode AstNode_members;
-// NOTE: 'type_node' is filled out by the parser. \
+// NOTE: 'type_node' is filled out by the parser.
// For a type such as '^^i32', the tree would look something like
//
// Typed Thing -> AstPointerType -> AstPointerType -> AstNode (symbol node)
struct AstDereference { AstTyped_base; AstTyped *expr; };
struct AstArrayAccess { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 elem_size; };
struct AstFieldAccess { AstTyped_base; AstTyped *expr; u64 offset; };
+struct AstSizeOf { AstTyped_base; AstType *so_type; u64 size; };
// Intruction Node
struct AstReturn { AstNode_base; AstTyped* expr; };
Token_Type_Keyword_For = 270,
Token_Type_Keyword_Break = 271,
Token_Type_Keyword_Continue = 272,
-
- Token_Type_Right_Arrow = 273,
- Token_Type_Left_Arrow = 274,
- Token_Type_Empty_Block = 275,
-
- Token_Type_Greater_Equal = 276,
- Token_Type_Less_Equal = 277,
- Token_Type_Equal_Equal = 278,
- Token_Type_Not_Equal = 279,
- Token_Type_Plus_Equal = 280,
- Token_Type_Minus_Equal = 281,
- Token_Type_Star_Equal = 282,
- Token_Type_Fslash_Equal = 283,
- Token_Type_Percent_Equal = 284,
-
- Token_Type_Symbol = 285,
- Token_Type_Literal_String = 286,
- Token_Type_Literal_Numeric = 287,
- Token_Type_Literal_True = 288,
- Token_Type_Literal_False = 289,
-
- Token_Type_Count = 290,
+ Token_Type_Keyword_Sizeof = 273,
+
+ Token_Type_Right_Arrow = 274,
+ Token_Type_Left_Arrow = 275,
+ Token_Type_Empty_Block = 276,
+
+ Token_Type_Greater_Equal = 277,
+ Token_Type_Less_Equal = 278,
+ Token_Type_Equal_Equal = 279,
+ Token_Type_Not_Equal = 280,
+ Token_Type_Plus_Equal = 281,
+ Token_Type_Minus_Equal = 282,
+ Token_Type_Star_Equal = 283,
+ Token_Type_Fslash_Equal = 284,
+ Token_Type_Percent_Equal = 285,
+
+ Token_Type_Symbol = 286,
+ Token_Type_Literal_String = 287,
+ Token_Type_Literal_Numeric = 288,
+ Token_Type_Literal_True = 289,
+ Token_Type_Literal_False = 290,
+
+ Token_Type_Count = 291,
} TokenType;
typedef struct OnyxFilePos {
}
foo_make :: proc -> ^Foo {
- return alloc(40) as ^Foo;
+ return alloc(sizeof Foo) as ^Foo;
}
foo_get :: proc (fooarr: ^Foo, i: i32) -> ^Foo {
// foo.foo = other_foo;
// print(foo.foo.i);
-
foo1 := foo_make();
foo1.v.y = 123.0f;
print(foo1.v.y);
- foo := alloc(40* 5) as ^Foo;
+ foo := alloc(sizeof Foo * 5) as ^Foo;
for i: 1, 6 {
foo[i - 1].v.x = (i + 3) as f32;
Mut2 :: struct {
foo : i32;
- other : ^Foo;
+ other : ^Mut1;
}
-mut_func :: proc #export (mut: ^Mut1) -> ^Foo {
+mut_func :: proc #export (mut: ^Mut1) -> ^Mut1 {
return mut.other.other;
}
Link :: struct {
data : i32;
- other_data : i32;
next : ^Link;
}
-link_create :: proc (data: i32, parent: ^Link) -> ^Link {
- link := alloc(12) as ^Link;
+link_create :: proc (data: i32, parent: ^^Link) {
+ link := alloc(sizeof Link) as ^Link;
link.data = data;
- link.other_data = 1234;
- link.next = parent;
- return link;
+ link.next = *parent;
+ *parent = link;
}
link_print :: proc (start: ^Link) {
walker := start;
while (walker as i32) != 0 {
- print(walker.next.data);
+ print(walker.data);
walker = walker.next;
}
}
link_test :: proc #export "main2" {
- dummy :: "H";
+ node_head := alloc(sizeof ^Link) as ^^Link;
+ *node_head = 0 as ^Link;
+
+ link_create(0, node_head);
+ link_create(1, node_head);
+ link_create(2, node_head);
+ link_create(3, node_head);
+ link_create(4, node_head);
- node1 := link_create(1, 0 as ^Link);
- node2 := link_create(2, node1);
- node3 := link_create(3, node2);
- node4 := link_create(4, node3);
- node5 := link_create(5, node4);
- link_print(node5);
+ link_print(*node_head);
}
\ No newline at end of file
CHECK(dereference, AstDereference* deref);
CHECK(array_access, AstArrayAccess* expr);
CHECK(field_access, AstFieldAccess* field);
+CHECK(size_of, AstSizeOf* so);
CHECK(global, AstGlobal* global);
CHECK(function, AstFunction* func);
CHECK(overloaded_function, AstOverloadedFunction* func);
return 0;
}
+CHECK(size_of, AstSizeOf* so) {
+ so->size = type_size_of(type_build_from_ast(semstate.allocator, so->so_type));
+
+ return 0;
+}
+
CHECK(expression, AstTyped* expr) {
if (expr->kind > Ast_Kind_Type_Start && expr->kind < Ast_Kind_Type_End) {
onyx_message_add(Msg_Type_Literal,
case Ast_Kind_Dereference: retval = check_dereference((AstDereference *) expr); break;
case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break;
case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess *) expr); break;
+ case Ast_Kind_Size_Of: retval = check_size_of((AstSizeOf *) expr); break;
case Ast_Kind_Global:
if (expr->type == NULL) {
LITERAL_TOKEN("for", 1, Token_Type_Keyword_For);
LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break);
LITERAL_TOKEN("continue", 1, Token_Type_Keyword_Continue);
+ LITERAL_TOKEN("sizeof", 1, Token_Type_Keyword_Sizeof);
LITERAL_TOKEN("true", 1, Token_Type_Literal_True);
LITERAL_TOKEN("false", 1, Token_Type_Literal_False);
LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow);
"expected token '%s', got '%s'",
"unexpected token '%s'",
"unknown type '%s'",
- "expected lval '%b'",
+ "cannot assign to '%b'",
"attempt to assign to constant '%b'",
"unknown symbol '%s'",
"unknown directive '%b'",
break;
}
+ case Token_Type_Keyword_Sizeof: {
+ AstSizeOf* so_node = make_node(AstSizeOf, Ast_Kind_Size_Of);
+ so_node->token = expect_token(parser, Token_Type_Keyword_Sizeof);
+ so_node->so_type = (AstType *) parse_type(parser);
+ so_node->type_node = (AstType *) &basic_type_i32;
+
+ retval = (AstTyped *) so_node;
+ break;
+ }
+
case Token_Type_Symbol: {
OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol);
AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol);
AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, NULL, "f64" }, &basic_types[Basic_Kind_F64] };
AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, NULL, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
-AstNumLit builtin_heap_start = { Ast_Kind_NumLit, Ast_Flag_Const, NULL, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
+static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_start ", { 0 } };
+AstNumLit builtin_heap_start = { Ast_Kind_NumLit, Ast_Flag_Const, &builtin_heap_start_token, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
const BuiltinSymbol builtin_symbols[] = {
{ "void", (AstNode *) &basic_type_void },
static AstType* symres_type(AstType* type);
static void symres_local(AstLocal** local);
static void symres_call(AstCall* call);
+static void symres_size_of(AstSizeOf* so);
static void symres_expression(AstTyped** expr);
static void symres_return(AstReturn* ret);
static void symres_if(AstIf* ifnode);
symres_statement_chain((AstNode *) call->arguments, (AstNode **) &call->arguments);
}
+static void symres_size_of(AstSizeOf* so) {
+ so->type_node = symres_type(so->type_node);
+ so->so_type = symres_type(so->so_type);
+}
+
static void symres_unaryop(AstUnaryOp** unaryop) {
if ((*unaryop)->operation == Unary_Op_Cast) {
(*unaryop)->type_node = symres_type((*unaryop)->type_node);
(*expr)->type_node = symres_type((*expr)->type_node);
break;
- case Ast_Kind_Address_Of:
- symres_expression(&((AstAddressOf *)(*expr))->expr);
- break;
-
- case Ast_Kind_Dereference:
- symres_expression(&((AstDereference *)(*expr))->expr);
- break;
+ case Ast_Kind_Address_Of: symres_expression(&((AstAddressOf *)(*expr))->expr); break;
+ case Ast_Kind_Dereference: symres_expression(&((AstDereference *)(*expr))->expr); break;
+ case Ast_Kind_Field_Access: symres_expression(&((AstFieldAccess *)(*expr))->expr); break;
+ case Ast_Kind_Size_Of: symres_size_of((AstSizeOf *)*expr); break;
case Ast_Kind_Array_Access:
symres_expression(&((AstArrayAccess *)(*expr))->addr);
symres_expression(&((AstArrayAccess *)(*expr))->expr);
break;
- case Ast_Kind_Field_Access:
- symres_expression(&((AstFieldAccess *)(*expr))->expr);
- break;
-
default:
DEBUG_HERE;
break;
"DEREFERENCE",
"ARRAY_ACCESS",
"FIELD_ACCESS",
+ "SIZE OF",
"IF",
"FOR",
bh_arr(WasmInstruction) code = *pcode;
i32 store_size = type_size_of(type);
- i32 is_integer = (type->Basic.flags & Basic_Flag_Integer)
- || (type->Basic.flags & Basic_Flag_Pointer);
+ i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
+ i32 is_integer = is_basic &&
+ ((type->Basic.flags & Basic_Flag_Integer)
+ || (type->Basic.flags & Basic_Flag_Pointer));
+ i32 is_float = is_basic && type->Basic.flags & Basic_Flag_Float;
if (is_integer) {
if (store_size == 1) WID(WI_I32_STORE_8, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 2) WID(WI_I32_STORE_16, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 4) WID(WI_I32_STORE, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 8) WID(WI_I64_STORE, ((WasmInstructionData) { alignment, offset }));
- } else {
+ } else if (is_float) {
if (store_size == 4) WID(WI_F32_STORE, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 8) WID(WI_F64_STORE, ((WasmInstructionData) { alignment, offset }));
+ } else {
+ onyx_message_add(Msg_Type_Literal,
+ (OnyxFilePos) { 0 },
+ "failed to generate store instruction");
}
*pcode = code;
bh_arr(WasmInstruction) code = *pcode;
i32 load_size = type_size_of(type);
- i32 is_integer = (type->Basic.flags & Basic_Flag_Integer)
- || (type->Basic.flags & Basic_Flag_Pointer);
- i32 is_unsigned = type->Basic.flags & Basic_Flag_Unsigned;
+ i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
+ i32 is_integer = is_basic &&
+ ((type->Basic.flags & Basic_Flag_Integer)
+ || (type->Basic.flags & Basic_Flag_Pointer));
+ i32 is_float = is_basic && type->Basic.flags & Basic_Flag_Float;
+ i32 is_unsigned = is_basic && type->Basic.flags & Basic_Flag_Unsigned;
WasmInstructionType instr = WI_NOP;
i32 alignment = type_get_alignment_log2(type);
else if (load_size == 8) instr = WI_I64_LOAD;
if (load_size < 4 && is_unsigned) instr += 1;
- } else {
+ } else if (is_float) {
if (load_size == 4) instr = WI_F32_LOAD;
else if (load_size == 8) instr = WI_F64_LOAD;
}
bh_arr(WasmInstruction) code = *pcode;
switch (unop->operation) {
- case Unary_Op_Negate:
- {
- TypeBasic* type = &unop->type->Basic;
-
- if (type->kind == Basic_Kind_I32
- || type->kind == Basic_Kind_I16
- || type->kind == Basic_Kind_I8) {
- WID(WI_I32_CONST, 0x00);
- compile_expression(mod, &code, unop->expr);
- WI(WI_I32_SUB);
+ case Unary_Op_Negate: {
+ TypeBasic* type = &unop->type->Basic;
- }
- else if (type->kind == Basic_Kind_I64) {
- WID(WI_I64_CONST, 0x00);
- compile_expression(mod, &code, unop->expr);
- WI(WI_I64_SUB);
+ if (type->kind == Basic_Kind_I32
+ || type->kind == Basic_Kind_I16
+ || type->kind == Basic_Kind_I8) {
+ WID(WI_I32_CONST, 0x00);
+ compile_expression(mod, &code, unop->expr);
+ WI(WI_I32_SUB);
- }
- else {
- compile_expression(mod, &code, unop->expr);
+ }
+ else if (type->kind == Basic_Kind_I64) {
+ WID(WI_I64_CONST, 0x00);
+ compile_expression(mod, &code, unop->expr);
+ WI(WI_I64_SUB);
- if (type->kind == Basic_Kind_F32)
- WI(WI_F32_NEG);
+ }
+ else {
+ compile_expression(mod, &code, unop->expr);
- if (type->kind == Basic_Kind_F64)
- WI(WI_F64_NEG);
- }
+ if (type->kind == Basic_Kind_F32)
+ WI(WI_F32_NEG);
- break;
+ if (type->kind == Basic_Kind_F64)
+ WI(WI_F64_NEG);
}
+ break;
+ }
+
case Unary_Op_Not:
compile_expression(mod, &code, unop->expr);
break;
}
+ case Ast_Kind_Size_Of: {
+ AstSizeOf* so = (AstSizeOf *) expr;
+ WID(WI_I32_CONST, so->size);
+ break;
+ }
+
default:
bh_printf("Unhandled case: %d\n", expr->kind);
DEBUG_HERE;
Type* from = cast->expr->type;
Type* to = cast->type;
+ if (from->kind == Type_Kind_Struct || to->kind == Type_Kind_Struct) {
+ onyx_message_add(Msg_Type_Literal,
+ cast->token->pos,
+ "cannot cast to or from a struct");
+ WI(WI_DROP);
+ return;
+ }
+
i32 fromidx = -1, toidx = -1;
if (from->Basic.flags & Basic_Flag_Pointer) {
fromidx = 8;