if (check_expression(&retnode->expr)) return 1;
if (!types_are_compatible(retnode->expr->type, semstate.expected_return_type)) {
- onyx_message_add(Msg_Type_Function_Return_Mismatch,
- retnode->expr->token->pos,
+ onyx_report_error(retnode->expr->token->pos,
+ "Expected to return a value of type '%s', returning value of type '%s'.",
type_get_name(retnode->expr->type),
type_get_name(semstate.expected_return_type));
return 1;
}
} else {
if (semstate.expected_return_type->Basic.size > 0) {
- onyx_message_add(Msg_Type_Literal,
- retnode->token->pos,
- "returning from non-void function without value");
+ onyx_report_error(retnode->token->pos, "returning from non-void function without value");
return 1;
}
}
if (check_expression(&ifnode->cond)) return 1;
if (!type_is_bool(ifnode->cond->type)) {
- onyx_message_add(Msg_Type_Literal,
- ifnode->cond->token->pos,
- "expected boolean type for condition");
+ onyx_report_error(ifnode->cond->token->pos, "expected boolean type for condition");
return 1;
}
if (check_expression(&whilenode->cond)) return 1;
if (!type_is_bool(whilenode->cond->type)) {
- onyx_message_add(Msg_Type_Literal,
- whilenode->cond->token->pos,
- "expected boolean type for condition");
+ onyx_report_error(whilenode->cond->token->pos, "expected boolean type for condition");
return 1;
}
fill_in_type((AstTyped *) fornode->var);
if (!type_is_integer(fornode->start->type)) {
- onyx_message_add(Msg_Type_Literal,
- fornode->start->token->pos,
- "expected expression of integer type for start");
+ onyx_report_error(fornode->start->token->pos, "expected expression of integer type for start");
return 1;
}
if (!type_is_integer(fornode->end->type)) {
- onyx_message_add(Msg_Type_Literal,
- fornode->end->token->pos,
- "expected expression of integer type for end");
+ onyx_report_error(fornode->end->token->pos, "expected expression of integer type for end");
return 1;
}
if (!type_is_integer(fornode->step->type)) {
- onyx_message_add(Msg_Type_Literal,
- fornode->step->token->pos,
- "expected expression of integer type for step");
+ onyx_report_error(fornode->step->token->pos, "expected expression of integer type for step");
return 1;
}
}
if (!types_are_compatible(fornode->end->type, fornode->start->type)) {
- onyx_message_add(Msg_Type_Literal,
- fornode->end->token->pos,
- "type of end does not match type of start");
+ onyx_report_error(fornode->end->token->pos, "type of end does not match type of start");
return 1;
}
if (!types_are_compatible(fornode->step->type, fornode->start->type)) {
- onyx_message_add(Msg_Type_Literal,
- fornode->start->token->pos,
- "type of step does not match type of start");
+ onyx_report_error(fornode->start->token->pos, "type of step does not match type of start");
return 1;
}
if (check_expression(&switchnode->expr)) return 1;
if (!type_is_integer(switchnode->expr->type) && switchnode->expr->type->kind != Type_Kind_Enum) {
- onyx_message_add(Msg_Type_Literal,
- switchnode->expr->token->pos,
- "expected integer or enum type for switch expression");
+ onyx_report_error(switchnode->expr->token->pos, "expected integer or enum type for switch expression");
return 1;
}
}
if (sc->value->kind != Ast_Kind_NumLit) {
- onyx_message_add(Msg_Type_Literal,
- sc->value->token->pos,
- "case statement expected compile time known integer");
+ onyx_report_error(sc->value->token->pos, "case statement expected compile time known integer");
return 1;
}
switchnode->max_case = bh_max(switchnode->max_case, value);
if (bh_imap_has(&switchnode->case_map, value)) {
- onyx_message_add(Msg_Type_Multiple_Cases,
- sc->value->token->pos,
- value);
+ onyx_report_error(sc->value->token->pos, "Multiple cases for values '%d'.", value);
return 1;
}
continue;
}
- onyx_message_add(Msg_Type_Literal,
- call->token->pos,
- "unable to match overloaded function");
+ onyx_report_error(call->token->pos, "unable to match overloaded function");
return NULL;
}
AstFunction* callee = (AstFunction *) call->callee;
if (callee->kind == Ast_Kind_Symbol) {
- onyx_message_add(Msg_Type_Unresolved_Symbol,
- callee->token->pos,
- callee->token->text, callee->token->length);
+ onyx_report_error(callee->token->pos, "Unresolved symbol '%b'.", callee->token->text, callee->token->length);
return 1;
}
if (check_expression((AstTyped **) &actual_param)) return 1;
if (actual_param->value->kind == Ast_Kind_Overloaded_Function) {
- onyx_message_add(Msg_Type_Literal,
- actual_param->token->pos,
- "cannot pass overloaded functions as parameters.");
+ onyx_report_error(actual_param->token->pos, "Cannot pass overloaded functions as parameters.");
return 1;
}
if (type_is_structlike_strict(actual_param->value->type)) {
if (!type_structlike_is_simple(actual_param->value->type)) {
- onyx_message_add(Msg_Type_Literal,
- actual_param->token->pos,
- "can only pass simple structs as parameters (no nested structures). passing by pointer is the only way for now.");
+ onyx_report_error(actual_param->token->pos,
+ "Can only pass simple structs as parameters (no nested structures). passing by pointer is the only way for now.");
return 1;
}
}
fill_in_type((AstTyped *) callee);
if (callee->type->kind != Type_Kind_Function) {
- onyx_message_add(Msg_Type_Call_Non_Function,
- call->token->pos,
+ onyx_report_error(call->token->pos,
+ "Attempting to call something that is not a function, '%b'.",
callee->token->text, callee->token->length);
return 1;
}
i32 arg_pos = 0;
while (arg_pos < callee->type->Function.param_count && actual_param != NULL) {
if (!types_are_compatible(formal_params[arg_pos], actual_param->type)) {
- onyx_message_add(Msg_Type_Function_Param_Mismatch,
- actual_param->token->pos,
+ onyx_report_error(actual_param->token->pos,
+ "The function '%b' expects a value of type '%s' for parameter '%d', got '%s'.",
callee->token->text, callee->token->length,
type_get_name(formal_params[arg_pos]),
arg_pos,
}
if (arg_pos < callee->type->Function.param_count) {
- onyx_message_add(Msg_Type_Literal,
- call->token->pos,
- "too few arguments to function call");
+ onyx_report_error(call->token->pos, "Too few arguments to function call.");
return 1;
}
if (actual_param != NULL) {
- onyx_message_add(Msg_Type_Literal,
- call->token->pos,
- "too many arguments to function call");
+ onyx_report_error(call->token->pos, "Too many arguments to function call.");
return 1;
}
b32 check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) {
if (!assignment_is_ok) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "assignment not valid in expression");
+ onyx_report_error(binop->token->pos, "Assignment not valid in expression.");
return 1;
}
if (!is_lval((AstNode *) binop->left)) {
- onyx_message_add(Msg_Type_Not_Lval,
- binop->left->token->pos,
+ onyx_report_error(binop->left->token->pos,
+ "Cannot assign to '%b'.",
binop->left->token->text, binop->left->token->length);
return 1;
}
if ((binop->left->flags & Ast_Flag_Const) != 0 && binop->left->type != NULL) {
- onyx_message_add(Msg_Type_Assign_Const,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Cannot assign to constant '%b.'.",
binop->left->token->text, binop->left->token->length);
return 1;
}
if (binop->right->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->right->token->text, binop->right->token->length);
return 1;
}
}
if (!types_are_compatible(binop->left->type, binop->right->type)) {
- onyx_message_add(Msg_Type_Assignment_Mismatch,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Cannot assign value of type '%s' to a '%s'.",
type_get_name(binop->left->type),
type_get_name(binop->right->type));
return 1;
AstBinaryOp* binop = *pbinop;
if (binop->left->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->left->token->text, binop->left->token->length);
return 1;
}
if (binop->right->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->right->token->text, binop->right->token->length);
return 1;
}
if (type_is_structlike_strict(binop->left->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "invalid type for left side of binary operator");
+ onyx_report_error(binop->token->pos, "Invalid type for left side of comparison operator.");
return 1;
}
if (type_is_structlike_strict(binop->right->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "invalid type for right side of binary operator");
+ onyx_report_error(binop->token->pos, "Invalid type for right side of comparison operator.");
return 1;
}
if (!types_are_compatible(binop->left->type, binop->right->type)) {
- onyx_message_add(Msg_Type_Binop_Mismatch,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Cannot compare '%s' to '%s'.",
type_get_name(binop->left->type),
type_get_name(binop->right->type));
return 1;
AstBinaryOp* binop = *pbinop;
if (binop->left->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->left->token->text, binop->left->token->length);
return 1;
}
if (binop->right->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->right->token->text, binop->right->token->length);
return 1;
}
if (!type_is_bool(binop->left->type) || !type_is_bool(binop->right->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "boolean operator expects boolean types for both operands");
+ onyx_report_error(binop->token->pos, "Boolean operator expects boolean types for both operands.");
return 1;
}
return check_binaryop_bool(pbinop);
if (binop->left->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->left->token->text, binop->left->token->length);
return 1;
}
if (binop->right->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Unable to resolve type for symbol '%b'.",
binop->right->token->text, binop->right->token->length);
return 1;
}
if (!type_is_numeric(binop->left->type) && !type_is_pointer(binop->left->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "expected numeric or pointer type for left side of binary operator");
+ onyx_report_error(binop->token->pos, "Expected numeric or pointer type for left side of binary operator.");
return 1;
}
if (!type_is_numeric(binop->right->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "expected numeric type for right side of binary operator");
+ onyx_report_error(binop->token->pos, "Expected numeric type for right side of binary operator.");
return 1;
}
if (type_is_pointer(binop->right->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "right side of binary operator is a pointer");
+ onyx_report_error(binop->token->pos, "Right side of binary operator is a pointer.");
return 1;
}
if (binop->left->type->kind == Type_Kind_Basic
&& binop->left->type->Basic.kind == Basic_Kind_Rawptr
&& !binop_is_compare(binop)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "cannot operate on a rawptr");
+ onyx_report_error(binop->token->pos, "Cannot operate on a 'rawptr'. Cast it to a another pointer type first.");
return 1;
}
b32 lptr = type_is_pointer(binop->left->type);
if (lptr && (binop->operation != Binary_Op_Add && binop->operation != Binary_Op_Minus)) {
- onyx_message_add(Msg_Type_Literal,
- binop->token->pos,
- "this operator is not supported for these operands");
+ onyx_report_error(binop->token->pos, "This operator is not supported for these operands.");
return 1;
}
if (lptr) {
if (!type_is_integer(binop->right->type)) {
- onyx_message_add(Msg_Type_Literal,
- binop->right->token->pos,
- "expected integer type");
+ onyx_report_error(binop->right->token->pos, "Expected integer type.");
return 1;
}
}
if (!types_are_compatible(binop->left->type, binop->right->type)) {
- onyx_message_add(Msg_Type_Binop_Mismatch,
- binop->token->pos,
+ onyx_report_error(binop->token->pos,
+ "Mismatched types for binary operation. left: '%s', right: '%s'.",
type_get_name(binop->left->type),
type_get_name(binop->right->type));
return 1;
u32 mem_count = type_structlike_mem_count(sl->type);
if (mem_count != bh_arr_length(sl->values)) {
- onyx_message_add(Msg_Type_Literal,
- sl->token->pos,
- "incorrect number of initial values for this type");
+ onyx_report_error(sl->token->pos,
+ "'%s' expects %d values, given %d.",
+ type_get_name(sl->type),
+ bh_arr_length(sl->values),
+ mem_count);
return 1;
}
Type* formal = smem.type;
if (!types_are_compatible(formal, (*actual)->type)) {
- onyx_message_add(Msg_Type_Assignment_Mismatch,
- sl->token->pos,
+ onyx_report_error(sl->token->pos,
+ "Mismatched types for %d%s member, expected '%s, got '%s'.",
+ i, bh_num_suffix(i),
type_get_name(formal),
type_get_name((*actual)->type));
return 1;
&& aof->expr->kind != Ast_Kind_Field_Access
&& aof->expr->kind != Ast_Kind_Memres
&& aof->expr->kind != Ast_Kind_Local) {
- onyx_message_add(Msg_Type_Literal,
- aof->token->pos,
- "cannot take the address of this");
+ onyx_report_error(aof->token->pos, "Cannot take the address of value.");
return 1;
}
if (check_expression(&deref->expr)) return 1;
if (!type_is_pointer(deref->expr->type)) {
- onyx_message_add(Msg_Type_Literal,
- deref->token->pos,
- "cannot dereference non-pointer");
+ onyx_report_error(deref->token->pos, "Cannot dereference non-pointer value.");
return 1;
}
if (deref->expr->type == basic_type_rawptr.type) {
- onyx_message_add(Msg_Type_Literal,
- deref->token->pos,
- "cannot dereference rawptr");
+ onyx_report_error(deref->token->pos, "Cannot dereference 'rawptr'. Cast to another pointer type first.");
return 1;
}
if (check_expression(&aa->expr)) return 1;
if (!type_is_array_accessible(aa->addr->type)) {
- onyx_message_add(Msg_Type_Literal,
- aa->token->pos,
- "expected pointer or array type for left of array access");
+ onyx_report_error(aa->token->pos, "Expected pointer or array type for left of array access.");
return 1;
}
if (aa->expr->type->kind != Type_Kind_Basic
|| (aa->expr->type->Basic.kind != Basic_Kind_I32 && aa->expr->type->Basic.kind != Basic_Kind_U32)) {
- onyx_message_add(Msg_Type_Literal,
- aa->token->pos,
- "expected 32-bit integer type for index");
+ onyx_report_error(aa->token->pos, "Expected type u32 or i32 for index.");
return 1;
}
aa->type = aa->addr->type->Pointer.elem;
}
else {
- onyx_message_add(Msg_Type_Literal,
- aa->token->pos,
- "invalid type for left of array access");
+ onyx_report_error(aa->token->pos, "Invalid type for left of array access.");
return 1;
}
if (check_expression(&sl->hi)) return 1;
if (!type_is_pointer(sl->addr->type)) {
- onyx_message_add(Msg_Type_Literal,
- sl->token->pos,
- "expected pointer or array type for left of slice creation");
+ onyx_report_error(sl->token->pos, "Expected pointer or array type for left of slice creation.");
return 1;
}
if (sl->lo->type->kind != Type_Kind_Basic
|| (sl->lo->type->Basic.kind != Basic_Kind_I32 && sl->lo->type->Basic.kind != Basic_Kind_U32)) {
- onyx_message_add(Msg_Type_Literal,
- sl->token->pos,
- "expected 32-bit integer type for lower index");
+ onyx_report_error(sl->lo->token->pos, "Expected type u32 or i32 for lower index.");
return 1;
}
if (sl->hi->type->kind != Type_Kind_Basic
|| (sl->hi->type->Basic.kind != Basic_Kind_I32 && sl->hi->type->Basic.kind != Basic_Kind_U32)) {
- onyx_message_add(Msg_Type_Literal,
- sl->token->pos,
- "expected 32-bit integer type for upper index");
+ onyx_report_error(sl->hi->token->pos, "Expected type u32 or i32 for upper index.");
return 1;
}
else if (sl->addr->type->kind == Type_Kind_Array)
of = sl->addr->type->Array.elem;
else {
- onyx_message_add(Msg_Type_Literal,
- sl->token->pos,
- "invalid type for left of slice creation");
+ onyx_report_error(sl->token->pos, "Invalid type for left of slice creation.");
return 1;
}
if (check_expression(&field->expr)) return 1;
if (!type_is_structlike(field->expr->type)) {
- onyx_message_add(Msg_Type_Literal,
- field->token->pos,
- "cannot access field on non structures");
+ onyx_report_error(field->token->pos,
+ "Cannot access field '%b' on '%s'. Type is not a struct.",
+ field->token->text,
+ field->token->length,
+ type_get_name(field->expr->type));
return 1;
}
token_toggle_end(field->token);
StructMember smem;
if (!type_lookup_member(field->expr->type, field->token->text, &smem)) {
- onyx_message_add(Msg_Type_No_Field,
- field->token->pos,
+ onyx_report_error(field->token->pos,
+ "Field '%s' does not exists on '%s'.",
field->token->text,
type_get_name(field->expr->type));
token_toggle_end(field->token);
b32 check_expression(AstTyped** pexpr) {
AstTyped* expr = *pexpr;
if (expr->kind > Ast_Kind_Type_Start && expr->kind < Ast_Kind_Type_End) {
- onyx_message_add(Msg_Type_Literal,
- expr->token->pos,
- "type used as part of an expression");
+ onyx_report_error(expr->token->pos, "Type used as part of an expression.");
return 1;
}
case Ast_Kind_Block: retval = check_block((AstBlock *) expr); break;
case Ast_Kind_Symbol:
- onyx_message_add(Msg_Type_Unresolved_Symbol,
- expr->token->pos,
+ onyx_report_error(expr->token->pos,
+ "Unable to resolve symbol '%b'.",
expr->token->text, expr->token->length);
retval = 1;
break;
case Ast_Kind_Param:
if (expr->type == NULL) {
- onyx_message_add(Msg_Type_Literal,
- expr->token->pos,
- "local variable with unknown type");
+ onyx_report_error(expr->token->pos, "Parameter with unknown type. You should hopefully never see this.");
retval = 1;
}
break;
case Ast_Kind_Global:
if (expr->type == NULL) {
- onyx_message_add(Msg_Type_Literal,
- expr->token->pos,
- "global with unknown type");
+ onyx_report_error(expr->token->pos, "Global with unknown type.");
retval = 1;
}
break;
fill_in_type((AstTyped *) global);
if (global->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- global->token->pos,
+ onyx_report_error(global->token->pos,
+ "Unable to resolve type for global '%b'.",
global->exported_name->text,
global->exported_name->length);
case Ast_Kind_For: return check_for((AstFor *) stmt);
case Ast_Kind_Switch: return check_switch((AstSwitch *) stmt);
case Ast_Kind_Block: return check_block((AstBlock *) stmt);
- case Ast_Kind_Defer: {
- if (!semstate.defer_allowed) {
- onyx_message_add(Msg_Type_Literal,
- stmt->token->pos,
- "deferred statement not allowed in deferred block");
- return 1;
- }
-
- semstate.defer_allowed = 0;
- b32 state = check_statement(((AstDefer *) stmt)->stmt);
- semstate.defer_allowed = 1;
-
- return state;
- }
+ case Ast_Kind_Defer: return check_statement(((AstDefer *) stmt)->stmt);
case Ast_Kind_Binary_Op:
stmt->flags |= Ast_Flag_Expr_Ignored;
fill_in_type(value);
if (value->type == NULL) {
- onyx_message_add(Msg_Type_Unresolved_Type,
- value->token->pos,
+ onyx_report_error(value->token->pos,
+ "Unable to resolve type for local '%b'.",
value->token->text, value->token->length);
return 1;
}
b32 check_overloaded_function(AstOverloadedFunction* func) {
bh_arr_each(AstTyped *, node, func->overloads) {
if ((*node)->kind == Ast_Kind_Overloaded_Function) {
- onyx_message_add(Msg_Type_Literal,
- (*node)->token->pos,
- "overload option can not be another overloaded function (yet)");
+ onyx_report_error((*node)->token->pos, "Overload option can not be another overloaded function.");
return 1;
}
if ((*node)->kind != Ast_Kind_Function) {
- onyx_message_add(Msg_Type_Literal,
- (*node)->token->pos,
- "overload option not function");
+ onyx_report_error((*node)->token->pos, "Overload option not function.");
return 1;
}
bh_table(i32) mem_set;
bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members));
- if (bh_arr_length(s_node->members) == 0) {
- onyx_message_add(Msg_Type_Literal,
- s_node->token->pos,
- "empty structure");
- return 1;
- }
-
bh_arr_each(AstStructMember *, member, s_node->members) {
token_toggle_end((*member)->token);
if (bh_table_has(i32, mem_set, (*member)->token->text)) {
- onyx_message_add(Msg_Type_Duplicate_Member,
- (*member)->token->pos,
+ onyx_report_error((*member)->token->pos,
+ "Duplicate struct member '%s'.",
(*member)->token->text);
token_toggle_end((*member)->token);
AstLocal* local = param->local;
if (expect_default_param && param->default_value == NULL) {
- onyx_message_add(Msg_Type_Literal,
- local->token->pos,
- "all parameters must have default values after the first default valued parameter.");
+ onyx_report_error(local->token->pos,
+ "All parameters must have default values after the first default valued parameter.");
return 1;
}
fill_in_type((AstTyped *) local);
if (local->type == NULL) {
- onyx_message_add(Msg_Type_Literal,
- local->token->pos,
- "function parameter types must be known");
+ onyx_report_error(local->token->pos, "Function parameter types must be known.");
return 1;
}
if (local->type->kind != Type_Kind_Array
&& type_size_of(local->type) == 0) {
- onyx_message_add(Msg_Type_Literal,
- local->token->pos,
- "function parameters must have non-void types");
+ onyx_report_error(local->token->pos, "Function parameters cannot have zero-width types.");
return 1;
}
}
if ((func->flags & Ast_Flag_Exported) != 0) {
if ((func->flags & Ast_Flag_Foreign) != 0) {
- onyx_message_add(Msg_Type_Literal,
- func->token->pos,
- "exporting a foreign function");
+ onyx_report_error(func->token->pos, "exporting a foreign function");
return 1;
}
if ((func->flags & Ast_Flag_Intrinsic) != 0) {
- onyx_message_add(Msg_Type_Literal,
- func->token->pos,
- "exporting a intrinsic function");
+ onyx_report_error(func->token->pos, "exporting a intrinsic function");
return 1;
}
if ((func->flags & Ast_Flag_Inline) != 0) {
- onyx_message_add(Msg_Type_Literal,
- func->token->pos,
- "exporting a inlined function");
+ onyx_report_error(func->token->pos, "exporting a inlined function");
return 1;
}
if (func->exported_name == NULL) {
- onyx_message_add(Msg_Type_Literal,
- func->token->pos,
- "exporting function without a name");
+ onyx_report_error(func->token->pos, "exporting function without a name");
return 1;
}
}
check_expression(&memres->initial_value);
if ((memres->initial_value->flags & Ast_Flag_Comptime) == 0) {
- onyx_message_add(Msg_Type_Literal,
- memres->initial_value->token->pos,
- "top level expressions must be compile time known");
+ onyx_report_error(memres->initial_value->token->pos, "Top level expressions must be compile time known.");
return 1;
}
Type* memres_type = memres->type;
if (!types_are_compatible(memres_type, memres->initial_value->type)) {
- onyx_message_add(Msg_Type_Binop_Mismatch,
- memres->token->pos,
+ onyx_report_error(memres->token->pos,
+ "Cannot assign value of type '%s' to a '%s'.",
type_get_name(memres_type),
type_get_name(memres->initial_value->type));
return 1;
#define WI(instr) bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }))
#define WID(instr, data) bh_arr_push(code, ((WasmInstruction){ instr, data }))
#define WIL(instr, data) bh_arr_push(code, ((WasmInstruction){ instr, { .l = data } }))
-#define COMPILE_FUNC(kind, ...) static void compile_ ## kind (OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, __VA_ARGS__)
-
-COMPILE_FUNC(function_body, AstFunction* fd);
-COMPILE_FUNC(block, AstBlock* block, b32 generate_block_headers);
-COMPILE_FUNC(statement, AstNode* stmt);
-COMPILE_FUNC(assignment, AstBinaryOp* assign);
-COMPILE_FUNC(store_instruction, Type* type, u32 offset);
-COMPILE_FUNC(load_instruction, Type* type, u32 offset);
-COMPILE_FUNC(if, AstIfWhile* if_node);
-COMPILE_FUNC(while, AstIfWhile* while_node);
-COMPILE_FUNC(for, AstFor* for_node);
-COMPILE_FUNC(switch, AstSwitch* switch_node);
-COMPILE_FUNC(defer, AstDefer* defer);
-COMPILE_FUNC(deferred_stmts, AstNode* node);
-COMPILE_FUNC(binop, AstBinaryOp* binop);
-COMPILE_FUNC(unaryop, AstUnaryOp* unop);
-COMPILE_FUNC(call, AstCall* call);
-COMPILE_FUNC(intrinsic_call, AstIntrinsicCall* call);
-COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return);
-COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return);
-COMPILE_FUNC(local_location, AstLocal* local, u64* offset_return);
-COMPILE_FUNC(memory_reservation_location, AstMemRes* memres);
-COMPILE_FUNC(location, AstTyped* expr);
-COMPILE_FUNC(struct_load, Type* type, u64 offset);
-COMPILE_FUNC(struct_lval, AstTyped* lval);
-COMPILE_FUNC(struct_store, Type* type, u64 offset);
-COMPILE_FUNC(struct_literal, AstStructLiteral* sl);
-COMPILE_FUNC(expression, AstTyped* expr);
-COMPILE_FUNC(cast, AstUnaryOp* cast);
-COMPILE_FUNC(return, AstReturn* ret);
-COMPILE_FUNC(stack_enter, u64 stacksize);
-COMPILE_FUNC(stack_leave, u32 unused);
-
-COMPILE_FUNC(function_body, AstFunction* fd) {
+#define EMIT_FUNC(kind, ...) static void emit_ ## kind (OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, __VA_ARGS__)
+
+EMIT_FUNC(function_body, AstFunction* fd);
+EMIT_FUNC(block, AstBlock* block, b32 generate_block_headers);
+EMIT_FUNC(statement, AstNode* stmt);
+EMIT_FUNC(assignment, AstBinaryOp* assign);
+EMIT_FUNC(store_instruction, Type* type, u32 offset);
+EMIT_FUNC(load_instruction, Type* type, u32 offset);
+EMIT_FUNC(if, AstIfWhile* if_node);
+EMIT_FUNC(while, AstIfWhile* while_node);
+EMIT_FUNC(for, AstFor* for_node);
+EMIT_FUNC(switch, AstSwitch* switch_node);
+EMIT_FUNC(defer, AstDefer* defer);
+EMIT_FUNC(deferred_stmts, AstNode* node);
+EMIT_FUNC(binop, AstBinaryOp* binop);
+EMIT_FUNC(unaryop, AstUnaryOp* unop);
+EMIT_FUNC(call, AstCall* call);
+EMIT_FUNC(intrinsic_call, AstIntrinsicCall* call);
+EMIT_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return);
+EMIT_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return);
+EMIT_FUNC(local_location, AstLocal* local, u64* offset_return);
+EMIT_FUNC(memory_reservation_location, AstMemRes* memres);
+EMIT_FUNC(location, AstTyped* expr);
+EMIT_FUNC(struct_load, Type* type, u64 offset);
+EMIT_FUNC(struct_lval, AstTyped* lval);
+EMIT_FUNC(struct_store, Type* type, u64 offset);
+EMIT_FUNC(struct_literal, AstStructLiteral* sl);
+EMIT_FUNC(expression, AstTyped* expr);
+EMIT_FUNC(cast, AstUnaryOp* cast);
+EMIT_FUNC(return, AstReturn* ret);
+EMIT_FUNC(stack_enter, u64 stacksize);
+EMIT_FUNC(stack_leave, u32 unused);
+
+EMIT_FUNC(function_body, AstFunction* fd) {
if (fd->body == NULL) return;
- compile_block(mod, pcode, fd->body, 0);
+ emit_block(mod, pcode, fd->body, 0);
}
-COMPILE_FUNC(block, AstBlock* block, b32 generate_block_headers) {
+EMIT_FUNC(block, AstBlock* block, b32 generate_block_headers) {
bh_arr(WasmInstruction) code = *pcode;
if (generate_block_headers) {
bh_imap_put(&mod->local_map, (u64) *local, local_allocate(mod->local_alloc, *local));
forll (AstNode, stmt, block->body, next) {
- compile_statement(mod, &code, stmt);
+ emit_statement(mod, &code, stmt);
}
- compile_deferred_stmts(mod, &code, (AstNode *) block);
+ emit_deferred_stmts(mod, &code, (AstNode *) block);
bh_arr_each(AstLocal *, local, block->locals)
local_free(mod->local_alloc, *local);
*pcode = code;
}
-COMPILE_FUNC(structured_jump, i32 jump_count, JumpType jump) {
+EMIT_FUNC(structured_jump, i32 jump_count, JumpType jump) {
bh_arr(WasmInstruction) code = *pcode;
static const u8 wants[Jump_Type_Count] = { 1, 2, 3 };
*pcode = code;
}
-COMPILE_FUNC(statement, AstNode* stmt) {
+EMIT_FUNC(statement, AstNode* stmt) {
bh_arr(WasmInstruction) code = *pcode;
switch (stmt->kind) {
- case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break;
- case Ast_Kind_If: compile_if(mod, &code, (AstIfWhile *) stmt); break;
- case Ast_Kind_While: compile_while(mod, &code, (AstIfWhile *) stmt); break;
- case Ast_Kind_For: compile_for(mod, &code, (AstFor *) stmt); break;
- case Ast_Kind_Switch: compile_switch(mod, &code, (AstSwitch *) stmt); break;
- case Ast_Kind_Jump: compile_structured_jump(mod, &code, ((AstJump *) stmt)->count, ((AstJump *) stmt)->jump); break;
- case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt, 1); break;
- case Ast_Kind_Defer: compile_defer(mod, &code, (AstDefer *) stmt); break;
- default: compile_expression(mod, &code, (AstTyped *) stmt); break;
+ case Ast_Kind_Return: emit_return(mod, &code, (AstReturn *) stmt); break;
+ case Ast_Kind_If: emit_if(mod, &code, (AstIfWhile *) stmt); break;
+ case Ast_Kind_While: emit_while(mod, &code, (AstIfWhile *) stmt); break;
+ case Ast_Kind_For: emit_for(mod, &code, (AstFor *) stmt); break;
+ case Ast_Kind_Switch: emit_switch(mod, &code, (AstSwitch *) stmt); break;
+ case Ast_Kind_Jump: emit_structured_jump(mod, &code, ((AstJump *) stmt)->count, ((AstJump *) stmt)->jump); break;
+ case Ast_Kind_Block: emit_block(mod, &code, (AstBlock *) stmt, 1); break;
+ case Ast_Kind_Defer: emit_defer(mod, &code, (AstDefer *) stmt); break;
+ default: emit_expression(mod, &code, (AstTyped *) stmt); break;
}
*pcode = code;
}
-COMPILE_FUNC(assignment, AstBinaryOp* assign) {
+EMIT_FUNC(assignment, AstBinaryOp* assign) {
bh_arr(WasmInstruction) code = *pcode;
if (type_is_structlike_strict(assign->right->type)) {
- compile_expression(mod, &code, assign->right);
- compile_struct_lval(mod, &code, assign->left);
+ emit_expression(mod, &code, assign->right);
+ emit_struct_lval(mod, &code, assign->left);
*pcode = code;
return;
if (lval->kind == Ast_Kind_Local) {
if (bh_imap_get(&mod->local_map, (u64) lval) & LOCAL_IS_WASM) {
u64 localidx = bh_imap_get(&mod->local_map, (u64) lval);
- compile_expression(mod, &code, assign->right);
+ emit_expression(mod, &code, assign->right);
WIL(WI_LOCAL_SET, localidx);
} else {
u64 offset = 0;
- compile_local_location(mod, &code, (AstLocal *) lval, &offset);
- compile_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code, lval->type, offset);
+ emit_local_location(mod, &code, (AstLocal *) lval, &offset);
+ emit_expression(mod, &code, assign->right);
+ emit_store_instruction(mod, &code, lval->type, offset);
}
} else if (lval->kind == Ast_Kind_Global) {
i32 globalidx = (i32) bh_imap_get(&mod->index_map, (u64) lval);
- compile_expression(mod, &code, assign->right);
+ emit_expression(mod, &code, assign->right);
WID(WI_GLOBAL_SET, globalidx);
} else if (lval->kind == Ast_Kind_Dereference) {
AstDereference* deref = (AstDereference *) lval;
- compile_expression(mod, &code, deref->expr);
- compile_expression(mod, &code, assign->right);
+ emit_expression(mod, &code, deref->expr);
+ emit_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code, deref->type, 0);
+ emit_store_instruction(mod, &code, deref->type, 0);
} else if (lval->kind == Ast_Kind_Array_Access) {
AstArrayAccess* aa = (AstArrayAccess *) lval;
u64 offset = 0;
- compile_array_access_location(mod, &code, aa, &offset);
- compile_expression(mod, &code, assign->right);
+ emit_array_access_location(mod, &code, aa, &offset);
+ emit_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code, aa->type, offset);
+ emit_store_instruction(mod, &code, aa->type, offset);
} else if (lval->kind == Ast_Kind_Field_Access) {
AstFieldAccess* field = (AstFieldAccess *) lval;
u64 offset = 0;
- compile_field_access_location(mod, &code, field, &offset);
- compile_expression(mod, &code, assign->right);
+ emit_field_access_location(mod, &code, field, &offset);
+ emit_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code, field->type, offset);
+ emit_store_instruction(mod, &code, field->type, offset);
} else if (lval->kind == Ast_Kind_Memres) {
AstMemRes* memres = (AstMemRes *) lval;
- compile_memory_reservation_location(mod, &code, memres);
- compile_expression(mod, &code, assign->right);
- compile_store_instruction(mod, &code, memres->type, 0);
+ emit_memory_reservation_location(mod, &code, memres);
+ emit_expression(mod, &code, assign->right);
+ emit_store_instruction(mod, &code, memres->type, 0);
} else {
assert(("Invalid lval", 0));
*pcode = code;
}
-COMPILE_FUNC(store_instruction, Type* type, u32 offset) {
+EMIT_FUNC(store_instruction, Type* type, u32 offset) {
bh_arr(WasmInstruction) code = *pcode;
if (type_is_structlike_strict(type)) {
- compile_struct_store(mod, pcode, type, offset);
+ emit_struct_store(mod, pcode, type, offset);
return;
}
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_Failed_Gen_Store,
- (OnyxFilePos) { 0 },
+ onyx_report_error((OnyxFilePos) { 0 },
+ "Failed to generate store instruction for type '%s'.",
type_get_name(type));
}
*pcode = code;
}
-COMPILE_FUNC(load_instruction, Type* type, u32 offset) {
+EMIT_FUNC(load_instruction, Type* type, u32 offset) {
bh_arr(WasmInstruction) code = *pcode;
if (type_is_structlike_strict(type)) {
- compile_struct_load(mod, pcode, type, offset);
+ emit_struct_load(mod, pcode, type, offset);
return;
}
WID(instr, ((WasmInstructionData) { alignment, offset }));
if (instr == WI_NOP) {
- onyx_message_add(Msg_Type_Failed_Gen_Load,
- (OnyxFilePos) { 0 },
- type_get_name(type));
+ onyx_report_error((OnyxFilePos) { 0 },
+ "Failed to generate load instruction for type '%s'.",
+ type_get_name(type));
}
*pcode = code;
}
-COMPILE_FUNC(if, AstIfWhile* if_node) {
+EMIT_FUNC(if, AstIfWhile* if_node) {
bh_arr(WasmInstruction) code = *pcode;
if (if_node->assignment != NULL) {
bh_imap_put(&mod->local_map, (u64) if_node->local, local_allocate(mod->local_alloc, if_node->local));
- compile_assignment(mod, &code, if_node->assignment);
+ emit_assignment(mod, &code, if_node->assignment);
}
- compile_expression(mod, &code, if_node->cond);
+ emit_expression(mod, &code, if_node->cond);
WID(WI_IF_START, 0x40);
bh_arr_push(mod->structured_jump_target, 0);
- if (if_node->true_stmt) compile_block(mod, &code, if_node->true_stmt, 0);
+ if (if_node->true_stmt) emit_block(mod, &code, if_node->true_stmt, 0);
if (if_node->false_stmt) {
WI(WI_ELSE);
if (if_node->false_stmt->kind == Ast_Kind_If) {
- compile_if(mod, &code, (AstIfWhile *) if_node->false_stmt);
+ emit_if(mod, &code, (AstIfWhile *) if_node->false_stmt);
} else {
- compile_block(mod, &code, if_node->false_stmt, 0);
+ emit_block(mod, &code, if_node->false_stmt, 0);
}
}
*pcode = code;
}
-COMPILE_FUNC(while, AstIfWhile* while_node) {
+EMIT_FUNC(while, AstIfWhile* while_node) {
bh_arr(WasmInstruction) code = *pcode;
if (while_node->assignment != NULL) {
bh_imap_put(&mod->local_map, (u64) while_node->local, local_allocate(mod->local_alloc, while_node->local));
- compile_assignment(mod, &code, while_node->assignment);
+ emit_assignment(mod, &code, while_node->assignment);
}
if (while_node->false_stmt == NULL) {
WID(WI_BLOCK_START, 0x40);
WID(WI_LOOP_START, 0x40);
- compile_expression(mod, &code, while_node->cond);
+ emit_expression(mod, &code, while_node->cond);
WI(WI_I32_EQZ);
WID(WI_COND_JUMP, 0x01);
bh_arr_push(mod->structured_jump_target, 1);
bh_arr_push(mod->structured_jump_target, 2);
- compile_block(mod, &code, while_node->true_stmt, 0);
+ emit_block(mod, &code, while_node->true_stmt, 0);
bh_arr_pop(mod->structured_jump_target);
bh_arr_pop(mod->structured_jump_target);
WI(WI_BLOCK_END);
} else {
- compile_expression(mod, &code, while_node->cond);
+ emit_expression(mod, &code, while_node->cond);
bh_arr_push(mod->structured_jump_target, 1);
bh_arr_push(mod->structured_jump_target, 2);
WID(WI_IF_START, 0x40);
WID(WI_LOOP_START, 0x40);
- compile_block(mod, &code, while_node->true_stmt, 0);
- compile_expression(mod, &code, while_node->cond);
+ emit_block(mod, &code, while_node->true_stmt, 0);
+ emit_expression(mod, &code, while_node->cond);
WID(WI_COND_JUMP, 0x00);
WI(WI_LOOP_END);
WI(WI_ELSE);
- compile_block(mod, &code, while_node->false_stmt, 0);
+ emit_block(mod, &code, while_node->false_stmt, 0);
WID(WI_IF_END, 0x40);
bh_arr_pop(mod->structured_jump_target);
*pcode = code;
}
-COMPILE_FUNC(for, AstFor* for_node) {
+EMIT_FUNC(for, AstFor* for_node) {
bh_arr(WasmInstruction) code = *pcode;
AstLocal* var = for_node->var;
WasmInstructionType ge_instr = var_type == WASM_TYPE_INT32 ? WI_I32_GE_S : WI_I64_GE_S;
if (it_is_local) {
- compile_expression(mod, &code, for_node->start);
+ emit_expression(mod, &code, for_node->start);
WIL(WI_LOCAL_SET, tmp);
} else {
- compile_local_location(mod, &code, var, &offset);
- compile_expression(mod, &code, for_node->start);
- compile_store_instruction(mod, &code, var->type, offset);
+ emit_local_location(mod, &code, var, &offset);
+ emit_expression(mod, &code, for_node->start);
+ emit_store_instruction(mod, &code, var->type, offset);
}
WID(WI_BLOCK_START, 0x40);
WIL(WI_LOCAL_GET, tmp);
} else {
offset = 0;
- compile_local_location(mod, &code, var, &offset);
- compile_load_instruction(mod, &code, var->type, offset);
+ emit_local_location(mod, &code, var, &offset);
+ emit_load_instruction(mod, &code, var->type, offset);
}
- compile_expression(mod, &code, for_node->end);
+ emit_expression(mod, &code, for_node->end);
WI(ge_instr);
WID(WI_COND_JUMP, 0x01);
- compile_block(mod, &code, for_node->stmt, 0);
+ emit_block(mod, &code, for_node->stmt, 0);
if (it_is_local) {
WIL(WI_LOCAL_GET, tmp);
- compile_expression(mod, &code, for_node->step);
+ emit_expression(mod, &code, for_node->step);
WI(add_instr);
WIL(WI_LOCAL_SET, tmp);
} else {
offset = 0;
- compile_local_location(mod, &code, var, &offset);
+ emit_local_location(mod, &code, var, &offset);
offset = 0;
- compile_local_location(mod, &code, var, &offset);
- compile_load_instruction(mod, &code, var->type, offset);
- compile_expression(mod, &code, for_node->step);
+ emit_local_location(mod, &code, var, &offset);
+ emit_load_instruction(mod, &code, var->type, offset);
+ emit_expression(mod, &code, for_node->step);
WI(add_instr);
- compile_store_instruction(mod, &code, var->type, offset);
+ emit_store_instruction(mod, &code, var->type, offset);
}
bh_arr_pop(mod->structured_jump_target);
*pcode = code;
}
-COMPILE_FUNC(switch, AstSwitch* switch_node) {
+EMIT_FUNC(switch, AstSwitch* switch_node) {
bh_arr(WasmInstruction) code = *pcode;
bh_imap block_map;
if (switch_node->assignment != NULL) {
bh_imap_put(&mod->local_map, (u64) switch_node->local, local_allocate(mod->local_alloc, switch_node->local));
- compile_assignment(mod, &code, switch_node->assignment);
+ emit_assignment(mod, &code, switch_node->assignment);
}
WID(WI_BLOCK_START, 0x40);
}
WID(WI_BLOCK_START, 0x40);
- compile_expression(mod, &code, switch_node->expr);
+ emit_expression(mod, &code, switch_node->expr);
if (switch_node->min_case != 0) {
WID(WI_I32_CONST, switch_node->min_case);
WI(WI_I32_SUB);
u64 bn = bh_imap_get(&block_map, (u64) sc->block);
- compile_block(mod, &code, sc->block, 0);
+ emit_block(mod, &code, sc->block, 0);
if (bh_arr_last(code).type != WI_JUMP)
WID(WI_JUMP, block_num - bn);
}
if (switch_node->default_case != NULL) {
- compile_block(mod, &code, switch_node->default_case, 0);
+ emit_block(mod, &code, switch_node->default_case, 0);
}
WI(WI_BLOCK_END);
*pcode = code;
}
-COMPILE_FUNC(defer, AstDefer* defer) {
+EMIT_FUNC(defer, AstDefer* defer) {
bh_arr_push(mod->deferred_stmts, ((DeferredStmt) {
.depth = bh_arr_length(mod->structured_jump_target),
.stmt = defer->stmt,
}));
}
-COMPILE_FUNC(deferred_stmts, AstNode* node) {
+EMIT_FUNC(deferred_stmts, AstNode* node) {
if (bh_arr_length(mod->deferred_stmts) == 0) return;
bh_arr(WasmInstruction) code = *pcode;
u64 depth = bh_arr_length(mod->structured_jump_target);
while (bh_arr_last(mod->deferred_stmts).depth == depth) {
- compile_statement(mod, &code, bh_arr_last(mod->deferred_stmts).stmt);
+ emit_statement(mod, &code, bh_arr_last(mod->deferred_stmts).stmt);
bh_arr_pop(mod->deferred_stmts);
}
/* BOR */ { WI_I32_OR, WI_I64_OR, WI_NOP, WI_NOP },
};
-COMPILE_FUNC(binop, AstBinaryOp* binop) {
+EMIT_FUNC(binop, AstBinaryOp* binop) {
bh_arr(WasmInstruction) code = *pcode;
if (binop_is_assignment(binop)) {
- compile_assignment(mod, &code, binop);
+ emit_assignment(mod, &code, binop);
*pcode = code;
return;
}
}
}
- compile_expression(mod, &code, binop->left);
- compile_expression(mod, &code, binop->right);
+ emit_expression(mod, &code, binop->left);
+ emit_expression(mod, &code, binop->right);
WI(binop_instr);
*pcode = code;
}
-COMPILE_FUNC(unaryop, AstUnaryOp* unop) {
+EMIT_FUNC(unaryop, AstUnaryOp* unop) {
bh_arr(WasmInstruction) code = *pcode;
switch (unop->operation) {
|| type->kind == Basic_Kind_I16
|| type->kind == Basic_Kind_I8) {
WID(WI_I32_CONST, 0x00);
- compile_expression(mod, &code, unop->expr);
+ emit_expression(mod, &code, unop->expr);
WI(WI_I32_SUB);
}
else if (type->kind == Basic_Kind_I64) {
WID(WI_I64_CONST, 0x00);
- compile_expression(mod, &code, unop->expr);
+ emit_expression(mod, &code, unop->expr);
WI(WI_I64_SUB);
}
else {
- compile_expression(mod, &code, unop->expr);
+ emit_expression(mod, &code, unop->expr);
if (type->kind == Basic_Kind_F32)
WI(WI_F32_NEG);
}
case Unary_Op_Not:
- compile_expression(mod, &code, unop->expr);
+ emit_expression(mod, &code, unop->expr);
WI(WI_I32_EQZ);
break;
- case Unary_Op_Cast: compile_cast(mod, &code, unop); break;
+ case Unary_Op_Cast: emit_cast(mod, &code, unop); break;
}
*pcode = code;
}
-COMPILE_FUNC(call, AstCall* call) {
+EMIT_FUNC(call, AstCall* call) {
bh_arr(WasmInstruction) code = *pcode;
for (AstArgument *arg = call->arguments;
arg != NULL;
arg = (AstArgument *) arg->next) {
- compile_expression(mod, &code, arg->value);
+ emit_expression(mod, &code, arg->value);
}
CallingConvention cc = type_function_get_cc(call->callee->type);
bh_arr_push(code, ((WasmInstruction){ WI_CALL, func_idx }));
} else {
- compile_expression(mod, &code, call->callee);
+ emit_expression(mod, &code, call->callee);
i32 type_idx = generate_type_idx(mod, call->callee->type);
WID(WI_CALL_INDIRECT, ((WasmInstructionData) { type_idx, 0x00 }));
WID(WI_GLOBAL_SET, stack_top_idx);
WID(WI_GLOBAL_GET, stack_top_idx);
- compile_load_instruction(mod, &code, return_type, 0);
+ emit_load_instruction(mod, &code, return_type, 0);
}
*pcode = code;
}
-COMPILE_FUNC(intrinsic_call, AstIntrinsicCall* call) {
+EMIT_FUNC(intrinsic_call, AstIntrinsicCall* call) {
bh_arr(WasmInstruction) code = *pcode;
i32 place_arguments_normally = 1;
for (AstArgument *arg = call->arguments;
arg != NULL;
arg = (AstArgument *) arg->next) {
- compile_expression(mod, &code, arg->value);
+ emit_expression(mod, &code, arg->value);
}
}
*pcode = code;
}
-COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return) {
+EMIT_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return) {
bh_arr(WasmInstruction) code = *pcode;
- compile_expression(mod, &code, aa->expr);
+ emit_expression(mod, &code, aa->expr);
if (aa->elem_size != 1) {
WID(WI_I32_CONST, aa->elem_size);
WI(WI_I32_MUL);
u64 offset = 0;
if (aa->addr->kind == Ast_Kind_Array_Access
&& aa->addr->type->kind == Type_Kind_Array) {
- compile_array_access_location(mod, &code, (AstArrayAccess *) aa->addr, &offset);
+ emit_array_access_location(mod, &code, (AstArrayAccess *) aa->addr, &offset);
} else if (aa->addr->kind == Ast_Kind_Field_Access
&& aa->addr->type->kind == Type_Kind_Array) {
- compile_field_access_location(mod, &code, (AstFieldAccess *) aa->addr, &offset);
+ emit_field_access_location(mod, &code, (AstFieldAccess *) aa->addr, &offset);
} else if ((aa->addr->kind == Ast_Kind_Local || aa->addr->kind == Ast_Kind_Param)
&& aa->addr->type->kind == Type_Kind_Array) {
- compile_local_location(mod, &code, (AstLocal *) aa->addr, &offset);
+ emit_local_location(mod, &code, (AstLocal *) aa->addr, &offset);
} else if (aa->addr->kind == Ast_Kind_Memres
&& aa->addr->type->kind != Type_Kind_Array) {
- compile_memory_reservation_location(mod, &code, (AstMemRes *) aa->addr);
+ emit_memory_reservation_location(mod, &code, (AstMemRes *) aa->addr);
} else {
- compile_expression(mod, &code, aa->addr);
+ emit_expression(mod, &code, aa->addr);
}
WI(WI_I32_ADD);
*pcode = code;
}
-COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return) {
+EMIT_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return) {
bh_arr(WasmInstruction) code = *pcode;
u64 offset = field->offset;
if (source_expr->kind == Ast_Kind_Array_Access
&& source_expr->type->kind != Type_Kind_Pointer) {
u64 o2 = 0;
- compile_array_access_location(mod, &code, (AstArrayAccess *) source_expr, &o2);
+ emit_array_access_location(mod, &code, (AstArrayAccess *) source_expr, &o2);
offset += o2;
} else if ((source_expr->kind == Ast_Kind_Local || source_expr->kind == Ast_Kind_Param)
&& source_expr->type->kind != Type_Kind_Pointer) {
u64 o2 = 0;
- compile_local_location(mod, &code, (AstLocal *) source_expr, &o2);
+ emit_local_location(mod, &code, (AstLocal *) source_expr, &o2);
offset += o2;
} else if (source_expr->kind == Ast_Kind_Memres
&& source_expr->type->kind != Type_Kind_Pointer) {
- compile_memory_reservation_location(mod, &code, (AstMemRes *) source_expr);
+ emit_memory_reservation_location(mod, &code, (AstMemRes *) source_expr);
} else {
- compile_expression(mod, &code, source_expr);
+ emit_expression(mod, &code, source_expr);
}
*offset_return = offset;
*pcode = code;
}
-COMPILE_FUNC(memory_reservation_location, AstMemRes* memres) {
+EMIT_FUNC(memory_reservation_location, AstMemRes* memres) {
bh_arr(WasmInstruction) code = *pcode;
WID(WI_I32_CONST, memres->addr);
*pcode = code;
}
-COMPILE_FUNC(local_location, AstLocal* local, u64* offset_return) {
+EMIT_FUNC(local_location, AstLocal* local, u64* offset_return) {
bh_arr(WasmInstruction) code = *pcode;
u64 local_offset = (u64) bh_imap_get(&mod->local_map, (u64) local);
*pcode = code;
}
-COMPILE_FUNC(struct_load, Type* type, u64 offset) {
+EMIT_FUNC(struct_load, Type* type, u64 offset) {
// NOTE: Expects the stack to look like:
// <location>
if (mem_count == 1) {
type_lookup_member_by_idx(type, 0, &smem);
- compile_load_instruction(mod, &code, smem.type, offset);
+ emit_load_instruction(mod, &code, smem.type, offset);
*pcode = code;
return;
}
fori (i, 0, mem_count) {
type_lookup_member_by_idx(type, i, &smem);
if (i != 0) WIL(WI_LOCAL_GET, tmp_idx);
- compile_load_instruction(mod, &code, smem.type, offset + smem.offset);
+ emit_load_instruction(mod, &code, smem.type, offset + smem.offset);
}
local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
*pcode = code;
}
-COMPILE_FUNC(struct_lval, AstTyped* lval) {
+EMIT_FUNC(struct_lval, AstTyped* lval) {
// NOTE: Expects the stack to look like:
// mem_1
// mem_2
u64 offset = 0;
switch (lval->kind) {
- case Ast_Kind_Local: compile_local_location(mod, &code, (AstLocal *) lval, &offset); break;
- case Ast_Kind_Dereference: compile_expression(mod, &code, ((AstDereference *) lval)->expr); break;
- case Ast_Kind_Array_Access: compile_array_access_location(mod, &code, (AstArrayAccess *) lval, &offset); break;
- case Ast_Kind_Field_Access: compile_field_access_location(mod, &code, (AstFieldAccess *) lval, &offset); break;
- case Ast_Kind_Memres: compile_memory_reservation_location(mod, &code, (AstMemRes *) lval); break;
+ case Ast_Kind_Local: emit_local_location(mod, &code, (AstLocal *) lval, &offset); break;
+ case Ast_Kind_Dereference: emit_expression(mod, &code, ((AstDereference *) lval)->expr); break;
+ case Ast_Kind_Array_Access: emit_array_access_location(mod, &code, (AstArrayAccess *) lval, &offset); break;
+ case Ast_Kind_Field_Access: emit_field_access_location(mod, &code, (AstFieldAccess *) lval, &offset); break;
+ case Ast_Kind_Memres: emit_memory_reservation_location(mod, &code, (AstMemRes *) lval); break;
default: assert(0);
}
- compile_struct_store(mod, &code, lval->type, offset);
+ emit_struct_store(mod, &code, lval->type, offset);
*pcode = code;
}
-COMPILE_FUNC(struct_store, Type* type, u64 offset) {
+EMIT_FUNC(struct_store, Type* type, u64 offset) {
// NOTE: Expects the stack to look like:
// mem_1
// mem_2
WIL(WI_LOCAL_GET, loc_idx);
}
- compile_struct_store(mod, &code, smem.type, offset + smem.offset);
+ emit_struct_store(mod, &code, smem.type, offset + smem.offset);
} else {
WasmType wt = onyx_type_to_wasm_type(smem.type);
WIL(WI_LOCAL_GET, loc_idx);
WIL(WI_LOCAL_GET, tmp_idx);
- compile_store_instruction(mod, &code, smem.type, offset + smem.offset);
+ emit_store_instruction(mod, &code, smem.type, offset + smem.offset);
local_raw_free(mod->local_alloc, wt);
}
*pcode = code;
}
-COMPILE_FUNC(struct_literal, AstStructLiteral* sl) {
+EMIT_FUNC(struct_literal, AstStructLiteral* sl) {
bh_arr(WasmInstruction) code = *pcode;
bh_arr_each(AstTyped *, val, sl->values) {
- compile_expression(mod, &code, *val);
+ emit_expression(mod, &code, *val);
}
*pcode = code;
}
-COMPILE_FUNC(location, AstTyped* expr) {
+EMIT_FUNC(location, AstTyped* expr) {
bh_arr(WasmInstruction) code = *pcode;
switch (expr->kind) {
case Ast_Kind_Param:
case Ast_Kind_Local: {
u64 offset = 0;
- compile_local_location(mod, &code, (AstLocal *) expr, &offset);
+ emit_local_location(mod, &code, (AstLocal *) expr, &offset);
if (offset != 0) {
WID(WI_I32_CONST, offset);
WI(WI_I32_ADD);
}
case Ast_Kind_Dereference: {
- compile_expression(mod, &code, ((AstDereference *) expr)->expr);
+ emit_expression(mod, &code, ((AstDereference *) expr)->expr);
break;
}
case Ast_Kind_Array_Access: {
AstArrayAccess* aa = (AstArrayAccess *) expr;
u64 offset = 0;
- compile_array_access_location(mod, &code, aa, &offset);
+ emit_array_access_location(mod, &code, aa, &offset);
if (offset != 0) {
WID(WI_I32_CONST, offset);
WI(WI_I32_ADD);
}
u64 offset = 0;
- compile_field_access_location(mod, &code, field, &offset);
+ emit_field_access_location(mod, &code, field, &offset);
if (offset != 0) {
WID(WI_I32_CONST, offset);
WI(WI_I32_ADD);
}
default: {
- DEBUG_HERE;
- onyx_message_add(Msg_Type_Literal,
- (OnyxFilePos) { 0 },
- "location unknown");
+ onyx_report_error(expr->token->pos, "Unable to generate locate for '%s'.", onyx_ast_node_kind_string(expr->kind));
break;
}
}
*pcode = code;
}
-COMPILE_FUNC(expression, AstTyped* expr) {
+EMIT_FUNC(expression, AstTyped* expr) {
bh_arr(WasmInstruction) code = *pcode;
switch (expr->kind) {
} else {
u64 offset = 0;
- compile_local_location(mod, &code, (AstLocal *) expr, &offset);
+ emit_local_location(mod, &code, (AstLocal *) expr, &offset);
if (expr->type->kind != Type_Kind_Array) {
- compile_load_instruction(mod, &code, expr->type, offset);
+ emit_load_instruction(mod, &code, expr->type, offset);
} else if (offset != 0) {
WID(WI_I32_CONST, offset);
WI(WI_I32_ADD);
}
case Ast_Kind_Struct_Literal: {
- compile_struct_literal(mod, &code, (AstStructLiteral *) expr);
+ emit_struct_literal(mod, &code, (AstStructLiteral *) expr);
break;
}
break;
}
- case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) expr, 1); break;
- case Ast_Kind_Call: compile_call(mod, &code, (AstCall *) expr); break;
- case Ast_Kind_Intrinsic_Call: compile_intrinsic_call(mod, &code, (AstIntrinsicCall *) expr); break;
- case Ast_Kind_Binary_Op: compile_binop(mod, &code, (AstBinaryOp *) expr); break;
- case Ast_Kind_Unary_Op: compile_unaryop(mod, &code, (AstUnaryOp *) expr); break;
+ case Ast_Kind_Block: emit_block(mod, &code, (AstBlock *) expr, 1); break;
+ case Ast_Kind_Call: emit_call(mod, &code, (AstCall *) expr); break;
+ case Ast_Kind_Intrinsic_Call: emit_intrinsic_call(mod, &code, (AstIntrinsicCall *) expr); break;
+ case Ast_Kind_Binary_Op: emit_binop(mod, &code, (AstBinaryOp *) expr); break;
+ case Ast_Kind_Unary_Op: emit_unaryop(mod, &code, (AstUnaryOp *) expr); break;
case Ast_Kind_Address_Of: {
AstAddressOf* aof = (AstAddressOf *) expr;
- compile_location(mod, &code, aof->expr);
+ emit_location(mod, &code, aof->expr);
break;
}
case Ast_Kind_Dereference: {
AstDereference* deref = (AstDereference *) expr;
- compile_expression(mod, &code, deref->expr);
- compile_load_instruction(mod, &code, deref->type, 0);
+ emit_expression(mod, &code, deref->expr);
+ emit_load_instruction(mod, &code, deref->type, 0);
break;
}
case Ast_Kind_Array_Access: {
AstArrayAccess* aa = (AstArrayAccess *) expr;
u64 offset = 0;
- compile_array_access_location(mod, &code, aa, &offset);
- compile_load_instruction(mod, &code, aa->type, offset);
+ emit_array_access_location(mod, &code, aa, &offset);
+ emit_load_instruction(mod, &code, aa->type, offset);
break;
}
}
u64 offset = 0;
- compile_field_access_location(mod, &code, field, &offset);
- compile_load_instruction(mod, &code, field->type, offset);
+ emit_field_access_location(mod, &code, field, &offset);
+ emit_load_instruction(mod, &code, field->type, offset);
break;
}
u64 tmp_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
- compile_expression(mod, &code, sl->lo);
+ emit_expression(mod, &code, sl->lo);
WIL(WI_LOCAL_TEE, tmp_local);
if (sl->elem_size != 1) {
WID(WI_I32_CONST, sl->elem_size);
WI(WI_I32_MUL);
}
- compile_expression(mod, &code, sl->addr);
+ emit_expression(mod, &code, sl->addr);
WI(WI_I32_ADD);
- compile_expression(mod, &code, sl->hi);
+ emit_expression(mod, &code, sl->hi);
WIL(WI_LOCAL_GET, tmp_local);
WI(WI_I32_SUB);
WID(WI_I64_CONST, ev->value->value.l);
}
else {
- onyx_message_add(Msg_Type_Literal,
- ev->token->pos,
- "invalid backing type for enum");
+ onyx_report_error(ev->token->pos, "Invalid backing type for enum.");
}
break;
}
case Ast_Kind_Memres: {
AstMemRes* memres = (AstMemRes *) expr;
WID(WI_I32_CONST, memres->addr);
- compile_load_instruction(mod, &code, memres->type, 0);
+ emit_load_instruction(mod, &code, memres->type, 0);
break;
}
/* PTR */ { WI_UNREACHABLE, WI_UNREACHABLE, 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) {
+EMIT_FUNC(cast, AstUnaryOp* cast) {
bh_arr(WasmInstruction) code = *pcode;
- compile_expression(mod, &code, cast->expr);
+ emit_expression(mod, &code, cast->expr);
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");
+ onyx_report_error(cast->token->pos, "Cannot cast to or from a struct.");
WI(WI_DROP);
*pcode = code;
return;
}
if (from->kind == Type_Kind_Slice || to->kind == Type_Kind_Slice) {
- onyx_message_add(Msg_Type_Literal,
- cast->token->pos,
- "cannot cast to or from a slice");
+ onyx_report_error(cast->token->pos, "Cannot cast to or from a slice.");
WI(WI_DROP);
*pcode = code;
return;
}
if (from->kind == Type_Kind_DynArray || to->kind == Type_Kind_DynArray) {
- onyx_message_add(Msg_Type_Literal,
- cast->token->pos,
- "cannot cast to or from a dynamic array");
+ onyx_report_error(cast->token->pos, "Cannot cast to or from a dynamic array.");
WI(WI_DROP);
*pcode = code;
return;
}
if (to->kind == Type_Kind_Function) {
- onyx_message_add(Msg_Type_Literal,
- cast->token->pos,
- "cannot cast to a function");
+ onyx_report_error(cast->token->pos, "Cannot cast to a function.");
WI(WI_DROP);
*pcode = code;
return;
if (to->kind == Type_Kind_Enum) to = to->Enum.backing;
if (from->kind == Type_Kind_Basic && from->Basic.kind == Basic_Kind_Void) {
- onyx_message_add(Msg_Type_Literal,
- cast->token->pos,
- "cannot cast from void");
+ onyx_report_error(cast->token->pos, "Cannot cast from void.");
WI(WI_DROP);
*pcode = code;
return;
WasmInstructionType cast_op = cast_map[fromidx][toidx];
if (cast_op == WI_UNREACHABLE) {
bh_printf("%d %d\n", fromidx, toidx);
- onyx_message_add(Msg_Type_Literal,
- cast->token->pos,
- "bad cast");
+ onyx_report_error(cast->token->pos, "Bad cast.");
}
else if (cast_op != WI_NOP) {
WI(cast_op);
*pcode = code;
}
-COMPILE_FUNC(return, AstReturn* ret) {
+EMIT_FUNC(return, AstReturn* ret) {
bh_arr(WasmInstruction) code = *pcode;
if (ret->expr) {
if (mod->curr_cc == CC_Return_Stack) {
if (type_is_structlike_strict(ret->expr->type)) {
- compile_expression(mod, &code, ret->expr);
+ emit_expression(mod, &code, ret->expr);
WIL(WI_LOCAL_GET, mod->stack_base_idx);
WID(WI_I32_CONST, type_size_of(ret->expr->type));
WI(WI_I32_SUB);
- compile_store_instruction(mod, &code, ret->expr->type, 0);
+ emit_store_instruction(mod, &code, ret->expr->type, 0);
} else {
WIL(WI_LOCAL_GET, mod->stack_base_idx);
WID(WI_I32_CONST, type_size_of(ret->expr->type));
WI(WI_I32_SUB);
- compile_expression(mod, &code, ret->expr);
- compile_store_instruction(mod, &code, ret->expr->type, 0);
+ emit_expression(mod, &code, ret->expr);
+ emit_store_instruction(mod, &code, ret->expr->type, 0);
}
} else {
- compile_expression(mod, &code, ret->expr);
+ emit_expression(mod, &code, ret->expr);
}
}
- compile_deferred_stmts(mod, &code, (AstNode *) ret);
+ emit_deferred_stmts(mod, &code, (AstNode *) ret);
if (bh_arr_length(mod->deferred_stmts) != 0) {
i32 i = bh_arr_length(mod->deferred_stmts) - 1;
while (i >= 0) {
- compile_statement(mod, &code, mod->deferred_stmts[i].stmt);
+ emit_statement(mod, &code, mod->deferred_stmts[i].stmt);
i--;
}
}
if (mod->has_stack_locals)
- compile_stack_leave(mod, &code, 0);
+ emit_stack_leave(mod, &code, 0);
WI(WI_RETURN);
*pcode = code;
}
-COMPILE_FUNC(stack_enter, u64 stacksize) {
+EMIT_FUNC(stack_enter, u64 stacksize) {
bh_arr(WasmInstruction) code = *pcode;
bh_align(stacksize, 16);
*pcode = code;
}
-COMPILE_FUNC(stack_leave, u32 unused) {
+EMIT_FUNC(stack_leave, u32 unused) {
bh_arr(WasmInstruction) code = *pcode;
u64 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
}
}
-static inline b32 should_compile_function(AstFunction* fd) {
+static inline b32 should_EMIT_FUNCtion(AstFunction* fd) {
// NOTE: Don't output intrinsic functions
if (fd->flags & Ast_Flag_Intrinsic) return 0;
}
-static void compile_function(OnyxWasmModule* mod, AstFunction* fd) {
- if (!should_compile_function(fd)) return;
+static void EMIT_FUNCtion(OnyxWasmModule* mod, AstFunction* fd) {
+ if (!should_EMIT_FUNCtion(fd)) return;
i32 type_idx = generate_type_idx(mod, fd->type);
}
// Generate code
- compile_function_body(mod, &wasm_func.code, fd);
+ emit_function_body(mod, &wasm_func.code, fd);
if (mod->has_stack_locals) {
- compile_stack_enter(mod, &wasm_func.code, mod->local_alloc->max_stack);
- compile_stack_leave(mod, &wasm_func.code, 0);
+ emit_stack_enter(mod, &wasm_func.code, mod->local_alloc->max_stack);
+ emit_stack_leave(mod, &wasm_func.code, 0);
}
}
bh_imap_clear(&mod->local_map);
}
-static void compile_global(OnyxWasmModule* module, AstGlobal* global) {
+static void emit_global(OnyxWasmModule* module, AstGlobal* global) {
WasmType global_type = onyx_type_to_wasm_type(global->type);
if (global->flags & Ast_Flag_Foreign) {
}
-static void compile_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
+static void emit_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
// NOTE: Allocating more than necessary, but there are no cases
// in a string literal that create more bytes than already
bh_arr_push(mod->data, datum);
}
-static void compile_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
+static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
switch (node->kind) {
case Ast_Kind_NumLit: {
switch (node->type->Basic.kind) {
//fallthrough
}
- default: onyx_message_add(Msg_Type_Literal,
- node->token->pos,
- "invalid data");
+ default: onyx_report_error(node->token->pos,
+ "Cannot generate constant data for '%s'.",
+ onyx_ast_node_kind_string(node->kind));
}
}
-static void compile_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
+static void emit_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
Type* effective_type = memres->type;
u64 alignment = type_alignment_of(effective_type);
if (memres->initial_value != NULL) {
u8* data = bh_alloc(global_heap_allocator, size);
- compile_raw_data(mod, data, memres->initial_value);
+ emit_raw_data(mod, data, memres->initial_value);
WasmDatum datum = {
.offset = offset,
mod->next_datum_offset = offset + size;
}
-static void compile_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {
+static void emit_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {
token_toggle_end(fc->filename);
if (bh_table_has(u32, mod->loaded_file_offsets, fc->filename->text)) {
bh_table_put(u32, mod->loaded_file_offsets, fc->filename->text, offset);
if (!bh_file_exists(fc->filename->text)) {
- onyx_message_add(Msg_Type_File_Not_Found,
- fc->filename->pos,
+ onyx_report_error(fc->filename->pos,
+ "Unable to open file for reading, '%s'.",
fc->filename->text);
token_toggle_end(fc->filename);
switch (entity->type) {
case Entity_Type_Function_Header: {
- if (!should_compile_function(entity->function)) break;
+ if (!should_EMIT_FUNCtion(entity->function)) break;
u64 func_idx;
if ((entity->function->flags & Ast_Flag_Foreign) != 0)
}
case Entity_Type_String_Literal: {
- compile_string_literal(module, (AstStrLit *) entity->strlit);
+ emit_string_literal(module, (AstStrLit *) entity->strlit);
break;
}
case Entity_Type_File_Contents: {
- compile_file_contents(module, (AstFileContents *) entity->file_contents);
+ emit_file_contents(module, (AstFileContents *) entity->file_contents);
break;
}
case Entity_Type_Memory_Reservation: {
- compile_memory_reservation(module, (AstMemRes *) entity->mem_res);
+ emit_memory_reservation(module, (AstMemRes *) entity->mem_res);
break;
}
- case Entity_Type_Function: compile_function(module, entity->function); break;
- case Entity_Type_Global: compile_global(module, entity->global); break;
+ case Entity_Type_Function: EMIT_FUNCtion(module, entity->function); break;
+ case Entity_Type_Global: emit_global(module, entity->global); break;
default: break;
}