extern AstBasicType basic_type_f64;
extern AstBasicType basic_type_rawptr;
+extern AstNumLit builtin_heap_start;
+
+typedef struct BuiltinSymbol {
+ char* sym;
+ AstNode* node;
+} BuiltinSymbol;
+
+extern const BuiltinSymbol builtin_symbols[];
+
+
// NOTE: Useful inlined functions
static inline b32 is_lval(AstNode* node) {
// NOTE: in-place insertion sort
sort :: proc (src: ^i32, len: i32) {
- i := 0;
- while i < len {
+ for i: 0, len {
smallest := i;
- j := i + 1;
- while j < len {
+ for j: i + 1, len
if src[j] < src[smallest] smallest = j;
- j += 1;
- }
tmp :: src[smallest];
src[smallest] = src[i];
src[i] = tmp;
-
- i += 1;
}
}
for i: 0, 10 print(i);
}
-str_test :: proc #export "main" {
- hello_str :: "Hello World!";
+str_test :: proc #export {
+ hello_str :: "Hello World! 123";
// Address of and dereference cancel each other out
print(^*hello_str);
}
// Don't need to bind this function to a symbol
-proc #export "main2" {
- print(min(10.0, 12.0));
+proc #export "main" {
+ print(__heap_start as i32);
- global_arr = 128 as ^i32;
+ global_arr = __heap_start as ^i32;
len :: 10;
- i := 0;
- while i < len {
- global_arr[i] = (len - i) * 10;
- i += 1;
- }
+ for i: 0, len global_arr[i] = (len - i) * 10;
print(global_arr, len);
print(1234567);
print(global_arr, len);
-
- str_test();
}
print_f64 :: proc #foreign "host" "print" (value: f64) ---
print_i32arr :: proc (arr: ^i32, len: i32) {
- i := 0;
- while i < len {
- print(arr[i]);
- i += 1;
- }
+ for i: 0, len print(arr[i]);
}
print_i64arr :: proc (arr: ^i64, len: i32) {
- i := 0;
- while i < len {
- print(arr[i]);
- i += 1;
- }
+ for i: 0, len print(arr[i]);
}
print_f32arr :: proc (arr: ^f32, len: i32) {
- i := 0;
- while i < len {
- print(arr[i]);
- i += 1;
- }
+ for i: 0, len print(arr[i]);
}
print_f64arr :: proc (arr: ^f64, len: i32) {
- i := 0;
- while i < len {
- print(arr[i]);
- i += 1;
- }
+ for i: 0, len print(arr[i]);
}
// NOTE: print null-terminated string
"proc",
"as",
"while",
+ "for",
"break",
"continue",
LITERAL_TOKEN("%=", 0, Token_Type_Percent_Equal);
// Symbols
- if (char_is_alpha(*tk.text)) {
+ if (char_is_alpha(*tk.text) || *tokenizer->curr == '_') {
u64 len = 0;
while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) {
len++;
static AstNode error_node = { Ast_Kind_Error, 0, NULL, NULL };
-AstBasicType basic_type_void = { { Ast_Kind_Basic_Type, 0, "void" }, &basic_types[Basic_Kind_Void] };
-AstBasicType basic_type_bool = { { Ast_Kind_Basic_Type, 0, "bool" }, &basic_types[Basic_Kind_Bool] };
-AstBasicType basic_type_i8 = { { Ast_Kind_Basic_Type, 0, "i8" }, &basic_types[Basic_Kind_I8] };
-AstBasicType basic_type_u8 = { { Ast_Kind_Basic_Type, 0, "u8" }, &basic_types[Basic_Kind_U8] };
-AstBasicType basic_type_i16 = { { Ast_Kind_Basic_Type, 0, "i16" }, &basic_types[Basic_Kind_I16] };
-AstBasicType basic_type_u16 = { { Ast_Kind_Basic_Type, 0, "u16" }, &basic_types[Basic_Kind_U16] };
-AstBasicType basic_type_i32 = { { Ast_Kind_Basic_Type, 0, "i32" }, &basic_types[Basic_Kind_I32] };
-AstBasicType basic_type_u32 = { { Ast_Kind_Basic_Type, 0, "u32" }, &basic_types[Basic_Kind_U32] };
-AstBasicType basic_type_i64 = { { Ast_Kind_Basic_Type, 0, "i64" }, &basic_types[Basic_Kind_I64] };
-AstBasicType basic_type_u64 = { { Ast_Kind_Basic_Type, 0, "u64" }, &basic_types[Basic_Kind_U64] };
-AstBasicType basic_type_f32 = { { Ast_Kind_Basic_Type, 0, "f32" }, &basic_types[Basic_Kind_F32] };
-AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, "f64" }, &basic_types[Basic_Kind_F64] };
-AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
-
// NOTE: Forward declarations
static void consume_token(OnyxParser* parser);
static void unconsume_token(OnyxParser* parser);
#define BH_DEBUG
#include "onyxsempass.h"
+AstBasicType basic_type_void = { { Ast_Kind_Basic_Type, 0, "void" }, &basic_types[Basic_Kind_Void] };
+AstBasicType basic_type_bool = { { Ast_Kind_Basic_Type, 0, "bool" }, &basic_types[Basic_Kind_Bool] };
+AstBasicType basic_type_i8 = { { Ast_Kind_Basic_Type, 0, "i8" }, &basic_types[Basic_Kind_I8] };
+AstBasicType basic_type_u8 = { { Ast_Kind_Basic_Type, 0, "u8" }, &basic_types[Basic_Kind_U8] };
+AstBasicType basic_type_i16 = { { Ast_Kind_Basic_Type, 0, "i16" }, &basic_types[Basic_Kind_I16] };
+AstBasicType basic_type_u16 = { { Ast_Kind_Basic_Type, 0, "u16" }, &basic_types[Basic_Kind_U16] };
+AstBasicType basic_type_i32 = { { Ast_Kind_Basic_Type, 0, "i32" }, &basic_types[Basic_Kind_I32] };
+AstBasicType basic_type_u32 = { { Ast_Kind_Basic_Type, 0, "u32" }, &basic_types[Basic_Kind_U32] };
+AstBasicType basic_type_i64 = { { Ast_Kind_Basic_Type, 0, "i64" }, &basic_types[Basic_Kind_I64] };
+AstBasicType basic_type_u64 = { { Ast_Kind_Basic_Type, 0, "u64" }, &basic_types[Basic_Kind_U64] };
+AstBasicType basic_type_f32 = { { Ast_Kind_Basic_Type, 0, "f32" }, &basic_types[Basic_Kind_F32] };
+AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, "f64" }, &basic_types[Basic_Kind_F64] };
+AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
+
+AstNumLit builtin_heap_start = { Ast_Kind_NumLit, 0, NULL, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
+
+const BuiltinSymbol builtin_symbols[] = {
+ { "void", (AstNode *) &basic_type_void },
+ { "bool", (AstNode *) &basic_type_bool },
+ { "i8", (AstNode *) &basic_type_i8 },
+ { "u8", (AstNode *) &basic_type_u8 },
+ { "i16", (AstNode *) &basic_type_i16 },
+ { "u16", (AstNode *) &basic_type_u16 },
+ { "i32", (AstNode *) &basic_type_i32 },
+ { "u32", (AstNode *) &basic_type_u32 },
+ { "i64", (AstNode *) &basic_type_i64 },
+ { "u64", (AstNode *) &basic_type_u64 },
+ { "f32", (AstNode *) &basic_type_f32 },
+ { "f64", (AstNode *) &basic_type_f64 },
+ { "rawptr", (AstNode *) &basic_type_rawptr },
+
+ { "__heap_start", (AstNode *) &builtin_heap_start },
+
+ { NULL, NULL },
+};
+
static b32 symbol_introduce(OnyxToken* tkn, AstNode* symbol);
+static void symbol_builtin_introduce(char* sym, AstNode *node);
static AstNode* symbol_resolve(OnyxToken* tkn);
-static void symbol_basic_type_introduce(AstBasicType* basic_type);
static void scope_enter(Scope* new_scope);
static void scope_leave();
return 1;
}
-static void symbol_basic_type_introduce(AstBasicType* basic_type) {
- bh_table_put(AstNode *, semstate.curr_scope->symbols, basic_type->name, (AstNode *) basic_type);
+static void symbol_builtin_introduce(char* sym, AstNode *node) {
+ bh_table_put(AstNode *, semstate.curr_scope->symbols, sym, node);
}
static AstNode* symbol_resolve(OnyxToken* tkn) {
scope_enter(semstate.global_scope);
// NOTE: Add types to global scope
- symbol_basic_type_introduce(&basic_type_void);
- symbol_basic_type_introduce(&basic_type_bool);
- symbol_basic_type_introduce(&basic_type_i8);
- symbol_basic_type_introduce(&basic_type_u8);
- symbol_basic_type_introduce(&basic_type_i16);
- symbol_basic_type_introduce(&basic_type_u16);
- symbol_basic_type_introduce(&basic_type_i32);
- symbol_basic_type_introduce(&basic_type_u32);
- symbol_basic_type_introduce(&basic_type_i64);
- symbol_basic_type_introduce(&basic_type_u64);
- symbol_basic_type_introduce(&basic_type_f32);
- symbol_basic_type_introduce(&basic_type_f64);
- symbol_basic_type_introduce(&basic_type_rawptr);
+ BuiltinSymbol* bsym = (BuiltinSymbol *) &builtin_symbols[0];
+ while (bsym->sym != NULL) {
+ symbol_builtin_introduce(bsym->sym, bsym->node);
+ bsym++;
+ }
bh_arr_each(AstBinding *, binding, program->bindings)
if (!symbol_introduce((*binding)->token, (*binding)->node)) return;
if (basic->size <= 4) return WASM_TYPE_INT32;
if (basic->size == 8) return WASM_TYPE_INT64;
}
+ if (basic->flags & Basic_Flag_Pointer) return WASM_TYPE_INT32;
if (basic->flags & Basic_Flag_Float) {
if (basic->size <= 4) return WASM_TYPE_FLOAT32;
if (basic->size == 8) return WASM_TYPE_FLOAT64;
*pcode = code;
}
-static const WasmInstructionType cast_map[][6] = {
- // I32 U32 I64 U64 F32 F64
- /* I32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S },
- /* U32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U },
- /* I64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_S, WI_F64_FROM_I64_S },
- /* U64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_U, WI_F64_FROM_I64_U },
- /* F32 */ { WI_I32_FROM_F32_S, WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP, WI_F64_FROM_F32 },
- /* F64 */ { WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64, WI_NOP, },
+static const WasmInstructionType cast_map[][9] = {
+ // I8 I16 I32 U32 I64 U64 F32 F64 PTR
+ /* I8 */ { WI_NOP, WI_I32_EXTEND_8_S, WI_I32_EXTEND_8_S, WI_NOP, WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_UNREACHABLE, WI_UNREACHABLE, WI_UNREACHABLE },
+ /* I16 */ { WI_NOP, WI_NOP, WI_I32_EXTEND_16_S, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U, WI_UNREACHABLE },
+ /* I32 */ { WI_NOP, WI_NOP, WI_NOP, WI_NOP, WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S, WI_NOP },
+ /* U32 */ { WI_NOP, WI_NOP, WI_NOP, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U, WI_NOP },
+ /* I64 */ { WI_NOP, WI_NOP, WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_S, WI_F64_FROM_I64_S, WI_I32_FROM_I64 },
+ /* U64 */ { WI_NOP, WI_NOP, WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_U, WI_F64_FROM_I64_U, WI_I32_FROM_I64 },
+ /* F32 */ { WI_UNREACHABLE, WI_UNREACHABLE, WI_I32_FROM_F32_S, WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP, WI_F64_FROM_F32, WI_UNREACHABLE },
+ /* F64 */ { WI_UNREACHABLE, WI_UNREACHABLE, WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64, WI_NOP, WI_UNREACHABLE },
+ /* PTR */ { WI_UNREACHABLE, WI_UNREACHABLE, WI_NOP, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_UNREACHABLE, WI_UNREACHABLE, WI_NOP },
};
COMPILE_FUNC(cast, AstUnaryOp* cast) {
Type* from = cast->expr->type;
Type* to = cast->type;
- i32 fromidx = 0, toidx = 0;
+ i32 fromidx = -1, toidx = -1;
if (from->Basic.flags & Basic_Flag_Integer) {
b32 unsign = (from->Basic.flags & Basic_Flag_Unsigned) != 0;
- if (from->Basic.size == 4 && !unsign) fromidx = 0;
- else if (from->Basic.size == 4 && unsign) fromidx = 1;
- else if (from->Basic.size == 8 && !unsign) fromidx = 2;
- else if (from->Basic.size == 8 && unsign) fromidx = 3;
+ if (from->Basic.size == 1 && !unsign) fromidx = 0;
+ else if (from->Basic.size == 1 && unsign) fromidx = -1;
+ else if (from->Basic.size == 2 && !unsign) fromidx = 1;
+ else if (from->Basic.size == 2 && unsign) fromidx = -1;
+ else if (from->Basic.size == 4 && !unsign) fromidx = 2;
+ else if (from->Basic.size == 4 && unsign) fromidx = 3;
+ else if (from->Basic.size == 8 && !unsign) fromidx = 4;
+ else if (from->Basic.size == 8 && unsign) fromidx = 5;
}
else if (from->Basic.flags & Basic_Flag_Float) {
- if (from->Basic.size == 4) fromidx = 4;
- else if (from->Basic.size == 8) fromidx = 5;
+ if (from->Basic.size == 4) fromidx = 6;
+ else if (from->Basic.size == 8) fromidx = 7;
+ }
+ else if (from->Basic.flags & Basic_Flag_Pointer) {
+ fromidx = 8;
}
if (to->Basic.flags & Basic_Flag_Integer) {
b32 unsign = (to->Basic.flags & Basic_Flag_Unsigned) != 0;
- if (to->Basic.size == 4 && !unsign) toidx = 0;
- else if (to->Basic.size == 4 && unsign) toidx = 1;
- else if (to->Basic.size == 8 && !unsign) toidx = 2;
- else if (to->Basic.size == 8 && unsign) toidx = 3;
+ if (to->Basic.size == 1 && !unsign) toidx = 0;
+ else if (to->Basic.size == 1 && unsign) toidx = -1;
+ else if (to->Basic.size == 2 && !unsign) toidx = 1;
+ else if (to->Basic.size == 2 && unsign) toidx = -1;
+ else if (to->Basic.size == 4 && !unsign) toidx = 2;
+ else if (to->Basic.size == 4 && unsign) toidx = 3;
+ else if (to->Basic.size == 8 && !unsign) toidx = 4;
+ else if (to->Basic.size == 8 && unsign) toidx = 5;
}
else if (to->Basic.flags & Basic_Flag_Float) {
- if (to->Basic.size == 4) toidx = 4;
- else if (to->Basic.size == 8) toidx = 5;
+ if (to->Basic.size == 4) toidx = 6;
+ else if (to->Basic.size == 8) toidx = 7;
+ }
+ else if (to->Basic.flags & Basic_Flag_Pointer) {
+ toidx = 8;
}
- WasmInstructionType cast_op = cast_map[fromidx][toidx];
- if (cast_op != WI_NOP) {
- WI(cast_op);
+ if (fromidx != -1 && toidx != -1) {
+ WasmInstructionType cast_op = cast_map[fromidx][toidx];
+ if (cast_op == WI_UNREACHABLE) {
+ onyx_message_add(Msg_Type_Literal,
+ cast->token->pos,
+ "bad cast");
+ }
+ else if (cast_op != WI_NOP) {
+ WI(cast_op);
+ }
}
*pcode = code;
}
}
-
-
+ // NOTE: Round up to the nearest multiple of 16
+ builtin_heap_start.value.i =
+ (module->next_datum_offset & 15)
+ ? ((module->next_datum_offset >> 4) + 1) << 4
+ : module->next_datum_offset;
// NOTE: Then, compile everything
bh_arr_each(Entity, entity, program->entities) {