Calling main
This commit is contained in:
5
ast.cpp
5
ast.cpp
@@ -63,6 +63,7 @@ enum{
|
|||||||
AST_DECL = bit_flag(9),
|
AST_DECL = bit_flag(9),
|
||||||
AST_GLOBAL = bit_flag(10),
|
AST_GLOBAL = bit_flag(10),
|
||||||
AST_FLAG = bit_flag(11),
|
AST_FLAG = bit_flag(11),
|
||||||
|
AST_VAR_IS_CONST = bit_flag(12),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast{
|
struct Ast{
|
||||||
@@ -255,11 +256,15 @@ enum Ast_Decl_State{
|
|||||||
DECL_RESOLVING,
|
DECL_RESOLVING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef S32 Register_Index;
|
||||||
struct Ast_Decl: Ast{
|
struct Ast_Decl: Ast{
|
||||||
Ast_Decl_State state;
|
Ast_Decl_State state;
|
||||||
Intern_String name;
|
Intern_String name;
|
||||||
|
|
||||||
|
// Bytecode
|
||||||
void *bytecode_data_position;
|
void *bytecode_data_position;
|
||||||
|
Register_Index register_index;
|
||||||
|
|
||||||
|
|
||||||
Ast_Scope *scope;
|
Ast_Scope *scope;
|
||||||
Ast_Expr *typespec;
|
Ast_Expr *typespec;
|
||||||
|
|||||||
@@ -9,12 +9,7 @@ bc_emit_expr(Bc *b, Ast *ast){
|
|||||||
// @todo pass type and figure out what to do with untyped ??
|
// @todo pass type and figure out what to do with untyped ??
|
||||||
CASE(VALUE, Atom){
|
CASE(VALUE, Atom){
|
||||||
Register_Index dst = allocate_register(b);
|
Register_Index dst = allocate_register(b);
|
||||||
switch(node->type->kind){
|
emit_load_constant(b, node->pos, dst, node->value);
|
||||||
CASE_UINT: emit_load_constant_u64(b, node->pos, dst, bigint_as_unsigned(&node->big_int_val)); break;
|
|
||||||
CASE_SINT: emit_load_constant_s64(b, node->pos, dst, bigint_as_signed(&node->big_int_val)); break;
|
|
||||||
CASE_FLOAT: emit_load_constant_f64(b, node->pos, dst, node->f64_val); break;
|
|
||||||
invalid_default_case;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -34,34 +29,96 @@ bc_emit_expr(Bc *b, Ast *ast){
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Incomplete_Instruction{
|
||||||
|
Instruction *instruction;
|
||||||
|
Ast_Decl *decl;
|
||||||
|
};
|
||||||
|
|
||||||
function void
|
function void
|
||||||
compile_to_bc(){
|
emit_stmt(Bc *b, Ast *ast){
|
||||||
Bc bc = create_bytecode_interp();
|
|
||||||
Bc *b = &bc;
|
|
||||||
For_Named(pctx->ordered_decls, ast){
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
|
||||||
CASE(LAMBDA, Decl){
|
|
||||||
unused(node);
|
|
||||||
// node->bytecode_data_position = emit_lambda();
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(VAR, Decl){
|
CASE(VAR, Decl){
|
||||||
node->bytecode_data_position = exp_alloc(&b->memory, node->type->size, AF_ZeroMemory);
|
node->register_index = allocate_register(b);
|
||||||
if(node->expr){
|
if(is_flag_set(node->flags, AST_VAR_IS_CONST)){
|
||||||
Register_Index expression_index = bc_emit_expr(b, node->expr);
|
// emit_load_
|
||||||
Register_Index address_index = allocate_register(b);
|
|
||||||
emit_load_constant_address(b, node->pos, address_index, node->bytecode_data_position);
|
|
||||||
emit_memory(b, node->pos, BC_STORE_TO_MEMORY64, address_index, expression_index);
|
|
||||||
release_register(b, expression_index);
|
|
||||||
release_register(b, address_index);
|
|
||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
default:{}
|
default:{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
compile_to_bc(){
|
||||||
|
Intern_String intern_main = pctx->intern("main"_s);
|
||||||
|
B32 found_main = false;
|
||||||
|
|
||||||
|
Bc bc = create_bytecode_interp();
|
||||||
|
Bc *b = &bc;
|
||||||
|
|
||||||
|
// Scratch scratch;
|
||||||
|
// auto incomplete = array_make<Incomplete_Instruction>(scratch, 512);
|
||||||
|
|
||||||
|
Register_Index main_call_register = allocate_register(b);
|
||||||
|
Instruction *load_main_address = emit_load_constant(b, 0, main_call_register, {});
|
||||||
|
emit_call(b, 0, 0);
|
||||||
|
|
||||||
|
For_Named(pctx->ordered_decls, ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
|
||||||
|
CASE(LAMBDA, Decl){
|
||||||
|
Ast_Lambda *lambda = node->lambda;
|
||||||
|
if(!lambda->scope) break;
|
||||||
|
node->bytecode_data_position = b->instruction_pointer;
|
||||||
|
|
||||||
|
For(node->lambda->args){
|
||||||
|
it->register_index = allocate_register(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
For(lambda->scope->stmts){
|
||||||
|
emit_stmt(b, it);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(node->name == intern_main){
|
||||||
|
found_main = true;
|
||||||
|
load_main_address->constant.pointer = (U8 *)node->bytecode_data_position;
|
||||||
|
load_main_address->debug_pos = node->pos;
|
||||||
|
load_main_address->debug_type_flag = TYPE_POINTER;
|
||||||
|
}
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
CASE(VAR, Decl){
|
||||||
|
node->bytecode_data_position = exp_alloc(&b->memory, node->type->size, AF_ZeroMemory);
|
||||||
|
if(is_flag_set(node->flags, AST_VAR_IS_CONST)){
|
||||||
|
switch(node->type->kind){
|
||||||
|
CASE_UINT: *(U64 *)node->bytecode_data_position = bigint_as_unsigned(&node->big_int_val); break;
|
||||||
|
CASE_SINT: *(S64 *)node->bytecode_data_position = bigint_as_signed(&node->big_int_val); break;
|
||||||
|
CASE_FLOAT: *(F64 *)node->bytecode_data_position = node->f64_val; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(node->expr) compiler_error(node->pos, "Todo: Global variable with non constant expression");
|
||||||
|
|
||||||
|
// if(node->expr){
|
||||||
|
// Register_Index expression_index = bc_emit_expr(b, node->expr);
|
||||||
|
// Register_Index address_index = allocate_register(b);
|
||||||
|
// emit_load_constant_address(b, node->pos, address_index, node->bytecode_data_position);
|
||||||
|
// emit_memory(b, node->pos, BC_STORE_TO_MEMORY64, address_index, expression_index);
|
||||||
|
// release_register(b, expression_index);
|
||||||
|
// release_register(b, address_index);
|
||||||
|
// }
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found_main){
|
||||||
|
compiler_error(0, "Having a [main] function is required, it's an entry point of the application");
|
||||||
|
}
|
||||||
|
|
||||||
emit_end(b);
|
emit_end(b);
|
||||||
run_bytecode_interp(b);
|
run_bytecode_interp(b);
|
||||||
destroy_bytecode_interp(b);
|
destroy_bytecode_interp(b);
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ const char *op_name[] = {
|
|||||||
// *End* of enum generated using code_generating_script.py
|
// *End* of enum generated using code_generating_script.py
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef S32 Register_Index;
|
|
||||||
union Register{
|
union Register{
|
||||||
F64 f64;
|
F64 f64;
|
||||||
S64 s64;
|
S64 s64;
|
||||||
@@ -273,53 +272,45 @@ destroy_bytecode_interp(Bc *b){
|
|||||||
function Instruction *
|
function Instruction *
|
||||||
new_instruction(Bc *b, Token *pos){
|
new_instruction(Bc *b, Token *pos){
|
||||||
Instruction *i = exp_alloc_type(&b->instructions, Instruction);
|
Instruction *i = exp_alloc_type(&b->instructions, Instruction);
|
||||||
|
b->instruction_pointer = i + 1;
|
||||||
|
|
||||||
i->di = b->dis++;
|
i->di = b->dis++;
|
||||||
i->debug_pos = pos;
|
i->debug_pos = pos;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function Instruction *
|
||||||
emit_call(Bc *b, Token *pos, Register_Index register_with_call_address, Register_Index register_with_last_argument){
|
emit_call(Bc *b, Token *pos, Register_Index register_with_call_address){
|
||||||
auto i = new_instruction(b, pos);
|
auto i = new_instruction(b, pos);
|
||||||
i->operation = BC_CALL;
|
i->operation = BC_CALL;
|
||||||
i->index_a = register_with_call_address;
|
i->index_a = register_with_call_address;
|
||||||
i->index_b = register_with_last_argument;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
emit_load_constant_f64(Bc *b, Token *pos, Register_Index dst, F64 constant){
|
emit_return(Bc *b, Token *pos){
|
||||||
auto i = new_instruction(b, pos);
|
auto i = new_instruction(b, pos);
|
||||||
i->operation = BC_LOAD_CONSTANT;
|
i->operation = BC_CALL_RETURN;
|
||||||
i->constant.f64 = constant;
|
|
||||||
i->index_c = dst;
|
|
||||||
i->debug_type_flag = TYPE_F64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function Instruction *
|
||||||
emit_load_constant_s64(Bc *b, Token *pos, Register_Index dst, S64 constant){
|
emit_load_constant(Bc *b, Token *pos, Register_Index dst, Value value){
|
||||||
auto i = new_instruction(b, pos);
|
auto i = new_instruction(b, pos);
|
||||||
i->operation = BC_LOAD_CONSTANT;
|
i->operation = BC_LOAD_CONSTANT;
|
||||||
i->constant.s64 = constant;
|
|
||||||
i->index_c = dst;
|
i->index_c = dst;
|
||||||
i->debug_type_flag = TYPE_S64;
|
|
||||||
|
if(value.type){
|
||||||
|
i->debug_type_flag = value.type->kind;
|
||||||
|
switch(value.type->kind){
|
||||||
|
case TYPE_POINTER:
|
||||||
|
CASE_UINT: i->constant.u64 = bigint_as_unsigned(&value.big_int_val); break;
|
||||||
|
CASE_SINT: i->constant.s64 = bigint_as_signed(&value.big_int_val); break;
|
||||||
|
CASE_FLOAT: i->constant.f64 = value.f64_val; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
return i;
|
||||||
emit_load_constant_u64(Bc *b, Token *pos, Register_Index dst, U64 constant){
|
|
||||||
auto i = new_instruction(b, pos);
|
|
||||||
i->operation = BC_LOAD_CONSTANT;
|
|
||||||
i->constant.u64 = constant;
|
|
||||||
i->index_c = dst;
|
|
||||||
i->debug_type_flag = TYPE_U64;
|
|
||||||
}
|
|
||||||
|
|
||||||
function void
|
|
||||||
emit_load_constant_address(Bc *b, Token *pos, Register_Index dst, void *address){
|
|
||||||
auto i = new_instruction(b, pos);
|
|
||||||
i->operation = BC_LOAD_CONSTANT;
|
|
||||||
i->constant.pointer = (U8 *)address;
|
|
||||||
i->index_c = dst;
|
|
||||||
i->debug_type_flag = TYPE_POINTER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -356,15 +347,14 @@ emit_arithmetic(Bc *b, Token *pos, Operation ins, Register_Index left, Register_
|
|||||||
function void
|
function void
|
||||||
emit_end(Bc *b){
|
emit_end(Bc *b){
|
||||||
Instruction *i = new_instruction(b, 0);
|
Instruction *i = new_instruction(b, 0);
|
||||||
i->di = b->dis++;
|
|
||||||
i->operation = BC_END_OF_INSTRUCTIONS;
|
i->operation = BC_END_OF_INSTRUCTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define R(x) (b->registers[b->top_call->first_register_index_in_window + (x)]) // Get register
|
#define R(x) (b->registers[b->top_call->first_register_index_in_window + (x)]) // Get register
|
||||||
#define bc_stack_push(b, T) (T *)bc__stack_push(b, sizeof(T))
|
#define bc_stack_push(b, T) (T *)bc_stack_push_size(b, sizeof(T))
|
||||||
|
|
||||||
function U8 *
|
function U8 *
|
||||||
bc__stack_push(Bc *b, U64 size){
|
bc_stack_push_size(Bc *b, U64 size){
|
||||||
U8 *result = (U8 *)b->stack_pointer;
|
U8 *result = (U8 *)b->stack_pointer;
|
||||||
b->stack_pointer += size;
|
b->stack_pointer += size;
|
||||||
assert(b->stack_pointer < b->stack_top);
|
assert(b->stack_pointer < b->stack_top);
|
||||||
@@ -435,7 +425,6 @@ run_bytecode_interp(Bc *b){
|
|||||||
|
|
||||||
case BC_CALL:{
|
case BC_CALL:{
|
||||||
Register_Index register_with_call_address = instr->index_a;
|
Register_Index register_with_call_address = instr->index_a;
|
||||||
// Register_Index register_with_last_argument = instr->index_b;
|
|
||||||
Call_Frame *call = bc_push_call_frame(b, register_with_call_address);
|
Call_Frame *call = bc_push_call_frame(b, register_with_call_address);
|
||||||
call->saved_instruction_pointer = b->instruction_pointer;
|
call->saved_instruction_pointer = b->instruction_pointer;
|
||||||
b->instruction_pointer = (Instruction *)R(register_with_call_address).pointer;
|
b->instruction_pointer = (Instruction *)R(register_with_call_address).pointer;
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ if True:
|
|||||||
result += "};\n"
|
result += "};\n"
|
||||||
update_file("bytecode_interpreter.cpp", "enum", result)
|
update_file("bytecode_interpreter.cpp", "enum", result)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generate switch cases
|
# Generate switch cases
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
global_variable := 10 + 29
|
global_variable := 10 + 29
|
||||||
|
|
||||||
main :: ()
|
main :: ()
|
||||||
pass // a := 10 + 20
|
a := 10 + 20 // a := 10 + 20
|
||||||
@@ -1395,6 +1395,10 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
try_propagating_resolved_type_to_untyped_literals(node->expr, node->type);
|
try_propagating_resolved_type_to_untyped_literals(node->expr, node->type);
|
||||||
|
|
||||||
|
if(op.is_const){
|
||||||
|
set_flag(node->flags, AST_VAR_IS_CONST);
|
||||||
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user