Code will compile as 32 bit but will causes errors in the linker on Windows

This commit is contained in:
Ginger Bill
2017-06-19 15:55:09 +01:00
parent 178236d1ff
commit 5427d14416
11 changed files with 674 additions and 622 deletions
+22 -20
View File
@@ -269,7 +269,11 @@ void init_build_context(void) {
#if defined(GB_SYSTEM_WINDOWS)
bc->ODIN_OS = str_lit("windows");
bc->ODIN_ARCH = str_lit("amd64");
#if defined(GB_ARCH_64_BIT)
bc->ODIN_ARCH = str_lit("amd64");
#else
bc->ODIN_ARCH = str_lit("x86");
#endif
bc->ODIN_ENDIAN = str_lit("little");
#elif defined(GB_SYSTEM_OSX)
bc->ODIN_OS = str_lit("osx");
@@ -287,29 +291,27 @@ void init_build_context(void) {
// across OSs. It doesn't make sense to allocate extra data on the heap
// here, so I just #defined the linker flags to keep things concise.
#if defined(GB_SYSTEM_WINDOWS)
#define LINK_FLAG_X64 "/machine:x64"
#define LINK_FLAG_X86 "/machine:x86"
#define LINK_FLAG_X64 "/machine:x64"
#define LINK_FLAG_X86 "/machine:x86"
#elif defined(GB_SYSTEM_OSX)
// NOTE(zangent): MacOS systems are x64 only, so ld doesn't have
// an architecture option. All compilation done on MacOS must be x64.
GB_ASSERT(bc->ODIN_ARCH == "amd64");
// NOTE(zangent): MacOS systems are x64 only, so ld doesn't have
// an architecture option. All compilation done on MacOS must be x64.
GB_ASSERT(bc->ODIN_ARCH == "amd64");
#define LINK_FLAG_X64 ""
#define LINK_FLAG_X86 ""
#define LINK_FLAG_X64 ""
#define LINK_FLAG_X86 ""
#else
// Linux, but also BSDs and the like.
// NOTE(zangent): When clang is swapped out with ld as the linker,
// the commented flags here should be used. Until then, we'll have
// to use alternative build flags made for clang.
/*
#define LINK_FLAG_X64 "-m elf_x86_64"
#define LINK_FLAG_X86 "-m elf_i386"
*/
#define LINK_FLAG_X64 "-arch x86-64"
#define LINK_FLAG_X86 "-arch x86"
// Linux, but also BSDs and the like.
// NOTE(zangent): When clang is swapped out with ld as the linker,
// the commented flags here should be used. Until then, we'll have
// to use alternative build flags made for clang.
/*
#define LINK_FLAG_X64 "-m elf_x86_64"
#define LINK_FLAG_X86 "-m elf_i386"
*/
#define LINK_FLAG_X64 "-arch x86-64"
#define LINK_FLAG_X86 "-arch x86"
#endif
if (bc->ODIN_ARCH == "amd64") {
+17 -17
View File
@@ -12,7 +12,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
// TODO(bill): is this a good enough error message?
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
error_node(operand->expr,
error(operand->expr,
"Cannot assign built-in procedure `%s` in %.*s",
expr_str,
LIT(context_name));
@@ -108,7 +108,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
if (operand->mode != Addressing_Constant) {
// TODO(bill): better error
gbString str = expr_to_string(operand->expr);
error_node(operand->expr, "`%s` is not a constant", str);
error(operand->expr, "`%s` is not a constant", str);
gb_string_free(str);
if (e->type == NULL) {
e->type = t_invalid;
@@ -117,7 +117,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
}
if (!is_type_constant_type(operand->type)) {
gbString type_str = type_to_string(operand->type);
error_node(operand->expr, "Invalid constant type: `%s`", type_str);
error(operand->expr, "Invalid constant type: `%s`", type_str);
gb_string_free(type_str);
if (e->type == NULL) {
e->type = t_invalid;
@@ -172,7 +172,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
Type *t = check_type(c, type_expr);
if (!is_type_constant_type(t)) {
gbString str = type_to_string(t);
error_node(type_expr, "Invalid constant type `%s`", str);
error(type_expr, "Invalid constant type `%s`", str);
gb_string_free(str);
e->type = t_invalid;
return;
@@ -279,18 +279,18 @@ void init_entity_foreign_library(Checker *c, Entity *e) {
if (ident == NULL) {
error(e->token, "foreign entiies must declare which library they are from");
} else if (ident->kind != AstNode_Ident) {
error_node(ident, "foreign library names must be an identifier");
error(ident, "foreign library names must be an identifier");
} else {
String name = ident->Ident.string;
Entity *found = scope_lookup_entity(c->context.scope, name);
if (found == NULL) {
if (name == "_") {
error_node(ident, "`_` cannot be used as a value type");
error(ident, "`_` cannot be used as a value type");
} else {
error_node(ident, "Undeclared name: %.*s", LIT(name));
error(ident, "Undeclared name: %.*s", LIT(name));
}
} else if (found->kind != Entity_LibraryName) {
error_node(ident, "`%.*s` cannot be used as a library name", LIT(name));
error(ident, "`%.*s` cannot be used as a library name", LIT(name));
} else {
// TODO(bill): Extra stuff to do with library names?
*foreign_library = found;
@@ -303,7 +303,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
GB_ASSERT(e->type == NULL);
if (d->proc_decl->kind != AstNode_ProcDecl) {
// TOOD(bill): Better error message
error_node(d->proc_decl, "Expected a procedure to check");
error(d->proc_decl, "Expected a procedure to check");
return;
}
@@ -336,11 +336,11 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
}
if (is_inline && is_no_inline) {
error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
error(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
}
if (is_foreign && is_export) {
error_node(pd->type, "A foreign procedure cannot have an `export` tag");
error(pd->type, "A foreign procedure cannot have an `export` tag");
}
@@ -352,10 +352,10 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
if (pd->body != NULL) {
if (is_foreign) {
error_node(pd->body, "A foreign procedure cannot have a body");
error(pd->body, "A foreign procedure cannot have a body");
}
if (proc_type->Proc.c_vararg) {
error_node(pd->body, "A procedure with a `#c_vararg` field cannot have a body");
error(pd->body, "A procedure with a `#c_vararg` field cannot have a body");
}
d->scope = c->context.scope;
@@ -367,7 +367,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
}
if (pt->result_count == 0 && is_require_results) {
error_node(pd->type, "`#require_results` is not needed on a procedure with no results");
error(pd->type, "`#require_results` is not needed on a procedure with no results");
} else {
pt->require_results = is_require_results;
}
@@ -393,13 +393,13 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
Type *other_type = base_type(f->type);
if (is_type_proc(this_type) && is_type_proc(other_type)) {
if (!are_signatures_similar_enough(this_type, other_type)) {
error_node(d->proc_decl,
error(d->proc_decl,
"Redeclaration of foreign procedure `%.*s` with different type signatures\n"
"\tat %.*s(%td:%td)",
LIT(name), LIT(pos.file), pos.line, pos.column);
}
} else if (!are_types_identical(this_type, other_type)) {
error_node(d->proc_decl,
error(d->proc_decl,
"Foreign entity `%.*s` previously declared elsewhere with a different type\n"
"\tat %.*s(%td:%td)",
LIT(name), LIT(pos.file), pos.line, pos.column);
@@ -424,7 +424,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
Entity *f = *found;
TokenPos pos = f->token.pos;
// TODO(bill): Better error message?
error_node(d->proc_decl,
error(d->proc_decl,
"Non unique linking name for procedure `%.*s`\n"
"\tother at %.*s(%td:%td)",
LIT(name), LIT(pos.file), pos.line, pos.column);
+223 -223
View File
File diff suppressed because it is too large Load Diff
+47 -47
View File
@@ -30,7 +30,7 @@ void check_stmt_list(Checker *c, Array<AstNode *> stmts, u32 flags) {
if (i+1 < max) {
switch (n->kind) {
case AstNode_ReturnStmt:
error_node(n, "Statements after this `return` are never executed");
error(n, "Statements after this `return` are never executed");
break;
}
}
@@ -283,7 +283,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
}
gbString lhs_expr = expr_to_string(lhs.expr);
gbString rhs_expr = expr_to_string(rhs->expr);
error_node(rhs->expr, "Cannot assign `%s` to bit field `%s`", rhs_expr, lhs_expr);
error(rhs->expr, "Cannot assign `%s` to bit field `%s`", rhs_expr, lhs_expr);
gb_string_free(rhs_expr);
gb_string_free(lhs_expr);
return NULL;
@@ -300,7 +300,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
if (tav.mode != Addressing_Variable) {
if (!is_type_pointer(tav.type)) {
gbString str = expr_to_string(lhs.expr);
error_node(lhs.expr, "Cannot assign to the value of a map `%s`", str);
error(lhs.expr, "Cannot assign to the value of a map `%s`", str);
gb_string_free(str);
return NULL;
}
@@ -316,7 +316,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
check_expr(c, &op_c, se->expr);
if (op_c.mode == Addressing_MapIndex) {
gbString str = expr_to_string(lhs.expr);
error_node(lhs.expr, "Cannot assign to record field `%s` in map", str);
error(lhs.expr, "Cannot assign to record field `%s` in map", str);
gb_string_free(str);
return NULL;
}
@@ -324,9 +324,9 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
gbString str = expr_to_string(lhs.expr);
if (lhs.mode == Addressing_Immutable) {
error_node(lhs.expr, "Cannot assign to an immutable: `%s`", str);
error(lhs.expr, "Cannot assign to an immutable: `%s`", str);
} else {
error_node(lhs.expr, "Cannot assign to `%s`", str);
error(lhs.expr, "Cannot assign to `%s`", str);
}
gb_string_free(str);
} break;
@@ -394,11 +394,11 @@ void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, ws->cond);
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
error_node(ws->cond, "Non-constant boolean `when` condition");
error(ws->cond, "Non-constant boolean `when` condition");
return;
}
if (ws->body == NULL || ws->body->kind != AstNode_BlockStmt) {
error_node(ws->cond, "Invalid body for `when` statement");
error(ws->cond, "Invalid body for `when` statement");
return;
}
if (operand.value.kind == ExactValue_Bool &&
@@ -413,7 +413,7 @@ void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
check_when_stmt(c, &ws->else_stmt->WhenStmt, flags);
break;
default:
error_node(ws->else_stmt, "Invalid `else` statement in `when` statement");
error(ws->else_stmt, "Invalid `else` statement in `when` statement");
break;
}
}
@@ -425,18 +425,18 @@ void check_label(Checker *c, AstNode *label) {
}
ast_node(l, Label, label);
if (l->name->kind != AstNode_Ident) {
error_node(l->name, "A label's name must be an identifier");
error(l->name, "A label's name must be an identifier");
return;
}
String name = l->name->Ident.string;
if (name == "_") {
error_node(l->name, "A label's name cannot be a blank identifier");
error(l->name, "A label's name cannot be a blank identifier");
return;
}
if (c->proc_stack.count == 0) {
error_node(l->name, "A label is only allowed within a procedure");
error(l->name, "A label is only allowed within a procedure");
return;
}
GB_ASSERT(c->context.decl != NULL);
@@ -445,7 +445,7 @@ void check_label(Checker *c, AstNode *label) {
for_array(i, c->context.decl->labels) {
BlockLabel bl = c->context.decl->labels[i];
if (bl.name == name) {
error_node(label, "Duplicate label with the name `%.*s`", LIT(name));
error(label, "Duplicate label with the name `%.*s`", LIT(name));
ok = false;
break;
}
@@ -594,7 +594,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
switch (operand.mode) {
case Addressing_Type: {
gbString str = type_to_string(operand.type);
error_node(node, "`%s` is not an expression", str);
error(node, "`%s` is not an expression", str);
gb_string_free(str);
} break;
case Addressing_NoValue:
@@ -609,14 +609,14 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (is_type_proc(t)) {
if (t->Proc.require_results) {
gbString expr_str = expr_to_string(ce->proc);
error_node(node, "`%s` requires that its results must be handled", expr_str);
error(node, "`%s` requires that its results must be handled", expr_str);
gb_string_free(expr_str);
}
}
return;
}
gbString expr_str = expr_to_string(operand.expr);
error_node(node, "Expression is not used: `%s`", expr_str);
error(node, "Expression is not used: `%s`", expr_str);
gb_string_free(expr_str);
} break;
}
@@ -624,7 +624,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_ast_node(ts, TagStmt, node);
// TODO(bill): Tag Statements
error_node(node, "Tag statements are not supported yet");
error(node, "Tag statements are not supported yet");
check_stmt(c, ts->stmt, flags);
case_end;
@@ -634,7 +634,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case Token_Inc: op = Token_Add; break;
case Token_Dec: op = Token_Sub; break;
default:
error_node(node, "Invalid inc/dec operation");
error(node, "Invalid inc/dec operation");
return;
}
@@ -646,7 +646,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (!is_type_integer(x.type) && !is_type_float(x.type)) {
gbString e = expr_to_string(s->expr);
gbString t = type_to_string(x.type);
error_node(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t);
error(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t);
gb_string_free(t);
gb_string_free(e);
return;
@@ -702,7 +702,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_assignment_variable(c, &operands[i], as->lhs[i]);
}
if (lhs_count != rhs_count) {
error_node(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
error(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
}
gb_temp_arena_memory_end(tmp);
@@ -754,7 +754,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, is->cond);
if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
error_node(is->cond, "Non-boolean condition in `if` statement");
error(is->cond, "Non-boolean condition in `if` statement");
}
check_stmt(c, is->body, mod_flags);
@@ -766,7 +766,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_stmt(c, is->else_stmt, mod_flags);
break;
default:
error_node(is->else_stmt, "Invalid `else` statement in `if` statement");
error(is->else_stmt, "Invalid `else` statement in `if` statement");
break;
}
}
@@ -800,7 +800,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
variables = tuple->variables;
}
if (rs->results.count == 0) {
error_node(node, "Expected %td return values, got 0", result_count);
error(node, "Expected %td return values, got 0", result_count);
} else {
// TokenPos pos = rs->token.pos;
// if (pos.line == 10) {
@@ -815,7 +815,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
// }
}
} else if (rs->results.count > 0) {
error_node(rs->results[0], "No return values expected");
error(rs->results[0], "No return values expected");
}
case_end;
@@ -832,7 +832,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Operand o = {Addressing_Invalid};
check_expr(c, &o, fs->cond);
if (o.mode != Addressing_Invalid && !is_type_boolean(o.type)) {
error_node(fs->cond, "Non-boolean condition in `for` statement");
error(fs->cond, "Non-boolean condition in `for` statement");
}
}
if (fs->post != NULL) {
@@ -840,7 +840,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (fs->post->kind != AstNode_AssignStmt &&
fs->post->kind != AstNode_IncDecStmt) {
error_node(fs->post, "`for` statement post statement must be a simple statement");
error(fs->post, "`for` statement post statement must be a simple statement");
}
}
check_stmt(c, fs->body, new_flags);
@@ -954,7 +954,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (operand.mode == Addressing_Type) {
if (!is_type_enum(operand.type)) {
gbString t = type_to_string(operand.type);
error_node(operand.expr, "Cannot iterate over the type `%s`", t);
error(operand.expr, "Cannot iterate over the type `%s`", t);
gb_string_free(t);
goto skip_expr;
} else {
@@ -1002,7 +1002,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (val == NULL) {
gbString s = expr_to_string(operand.expr);
gbString t = type_to_string(operand.type);
error_node(operand.expr, "Cannot iterate over `%s` of type `%s`", s, t);
error(operand.expr, "Cannot iterate over `%s` of type `%s`", s, t);
gb_string_free(t);
gb_string_free(s);
}
@@ -1040,7 +1040,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
entity = found;
}
} else {
error_node(name, "A variable declaration must be an identifier");
error(name, "A variable declaration must be an identifier");
}
if (entity == NULL) {
@@ -1089,7 +1089,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
if (is_type_vector(x.type)) {
gbString str = type_to_string(x.type);
error_node(x.expr, "Invalid match expression type: %s", str);
error(x.expr, "Invalid match expression type: %s", str);
gb_string_free(str);
break;
}
@@ -1107,13 +1107,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
default_stmt = stmt;
}
} else {
error_node(stmt, "Invalid AST - expected case clause");
error(stmt, "Invalid AST - expected case clause");
}
if (default_stmt != NULL) {
if (first_default != NULL) {
TokenPos pos = ast_node_token(first_default).pos;
error_node(stmt,
error(stmt,
"multiple `default` clauses\n"
"\tfirst at %.*s(%td:%td)",
LIT(pos.file), pos.line, pos.column);
@@ -1155,7 +1155,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (!is_type_ordered(x.type)) {
gbString str = type_to_string(x.type);
error_node(x.expr, "Unordered type `%s`, is invalid for an interval expression", str);
error(x.expr, "Unordered type `%s`, is invalid for an interval expression", str);
gb_string_free(str);
continue;
}
@@ -1229,7 +1229,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (are_types_identical(y.type, tap.type)) {
TokenPos pos = tap.token.pos;
gbString expr_str = expr_to_string(y.expr);
error_node(y.expr,
error(y.expr,
"Duplicate case `%s`\n"
"\tprevious case at %.*s(%td:%td)",
expr_str,
@@ -1276,7 +1276,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
MatchTypeKind match_type_kind = MatchType_Invalid;
if (ms->tag->kind != AstNode_AssignStmt) {
error_node(ms->tag, "Expected an `in` assignment for this type match statement");
error(ms->tag, "Expected an `in` assignment for this type match statement");
break;
}
@@ -1298,7 +1298,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
match_type_kind = check_valid_type_match_type(x.type);
if (check_valid_type_match_type(x.type) == MatchType_Invalid) {
gbString str = type_to_string(x.type);
error_node(x.expr, "Invalid type for this type match expression, got `%s`", str);
error(x.expr, "Invalid type for this type match expression, got `%s`", str);
gb_string_free(str);
break;
}
@@ -1317,13 +1317,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
default_stmt = stmt;
}
} else {
error_node(stmt, "Invalid AST - expected case clause");
error(stmt, "Invalid AST - expected case clause");
}
if (default_stmt != NULL) {
if (first_default != NULL) {
TokenPos pos = ast_node_token(first_default).pos;
error_node(stmt,
error(stmt,
"Multiple `default` clauses\n"
"\tfirst at %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column);
} else {
@@ -1334,7 +1334,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (lhs->kind != AstNode_Ident) {
error_node(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind]));
error(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind]));
break;
}
@@ -1372,7 +1372,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
if (!tag_type_found) {
gbString type_str = type_to_string(y.type);
error_node(y.expr, "Unknown tag type, got `%s`", type_str);
error(y.expr, "Unknown tag type, got `%s`", type_str);
gb_string_free(type_str);
continue;
}
@@ -1388,7 +1388,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (found) {
TokenPos pos = cc->token.pos;
gbString expr_str = expr_to_string(y.expr);
error_node(y.expr,
error(y.expr,
"Duplicate type case `%s`\n"
"\tprevious type case at %.*s(%td:%td)",
expr_str,
@@ -1469,7 +1469,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (bs->label != NULL) {
if (bs->label->kind != AstNode_Ident) {
error_node(bs->label, "A branch statement's label name must be an identifier");
error(bs->label, "A branch statement's label name must be an identifier");
return;
}
AstNode *ident = bs->label;
@@ -1477,12 +1477,12 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Operand o = {};
Entity *e = check_ident(c, &o, ident, NULL, NULL, false);
if (e == NULL) {
error_node(ident, "Undeclared label name: %.*s", LIT(name));
error(ident, "Undeclared label name: %.*s", LIT(name));
return;
}
add_entity_use(c, ident, e);
if (e->kind != Entity_Label) {
error_node(ident, "`%.*s` is not a label", LIT(name));
error(ident, "`%.*s` is not a label", LIT(name));
return;
}
}
@@ -1537,7 +1537,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
AstNode *foreign_library = fb->foreign_library;
bool ok = true;
if (foreign_library->kind != AstNode_Ident) {
error_node(foreign_library, "foreign library name must be an identifier");
error(foreign_library, "foreign library name must be an identifier");
ok = false;
}
@@ -1576,14 +1576,14 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (gd->flags & VarDeclFlag_thread_local) {
gd->flags &= ~VarDeclFlag_thread_local;
error_node(node, "`thread_local` may only be applied to a variable declaration");
error(node, "`thread_local` may only be applied to a variable declaration");
}
for_array(i, vd->names) {
AstNode *name = vd->names[i];
Entity *entity = NULL;
if (name->kind != AstNode_Ident) {
error_node(name, "A variable declaration must be an identifier");
error(name, "A variable declaration must be an identifier");
} else {
Token token = name->Ident;
String str = token.string;
+25 -25
View File
@@ -1438,23 +1438,23 @@ bool check_arity_match(Checker *c, AstNodeValueSpec *spec) {
if (rhs == 0) {
if (spec->type == NULL) {
error_node(spec->names[0], "Missing type or initial expression");
error(spec->names[0], "Missing type or initial expression");
return false;
}
} else if (lhs < rhs) {
if (lhs < spec->values.count) {
AstNode *n = spec->values[lhs];
gbString str = expr_to_string(n);
error_node(n, "Extra initial expression `%s`", str);
error(n, "Extra initial expression `%s`", str);
gb_string_free(str);
} else {
error_node(spec->names[0], "Extra initial expression");
error(spec->names[0], "Extra initial expression");
}
return false;
} else if (lhs > rhs && rhs != 1) {
AstNode *n = spec->names[rhs];
gbString str = expr_to_string(n);
error_node(n, "Missing expression for `%s`", str);
error(n, "Missing expression for `%s`", str);
gb_string_free(str);
return false;
}
@@ -1466,13 +1466,13 @@ void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws, bool
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, ws->cond);
if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
error_node(ws->cond, "Non-boolean condition in `when` statement");
error(ws->cond, "Non-boolean condition in `when` statement");
}
if (operand.mode != Addressing_Constant) {
error_node(ws->cond, "Non-constant condition in `when` statement");
error(ws->cond, "Non-constant condition in `when` statement");
}
if (ws->body == NULL || ws->body->kind != AstNode_BlockStmt) {
error_node(ws->cond, "Invalid body for `when` statement");
error(ws->cond, "Invalid body for `when` statement");
} else {
if (operand.value.kind == ExactValue_Bool &&
operand.value.value_bool) {
@@ -1486,7 +1486,7 @@ void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws, bool
check_collect_entities_from_when_stmt(c, &ws->else_stmt->WhenStmt, is_file_scope);
break;
default:
error_node(ws->else_stmt, "Invalid `else` statement in `when` statement");
error(ws->else_stmt, "Invalid `else` statement in `when` statement");
break;
}
}
@@ -1514,7 +1514,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
case_ast_node(ws, WhenStmt, decl);
if (c->context.scope->is_file) {
error_node(decl, "`when` statements are not allowed at file scope");
error(decl, "`when` statements are not allowed at file scope");
} else {
// Will be handled later
}
@@ -1538,7 +1538,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
for_array(i, vs->names) {
AstNode *name = vs->names[i];
if (name->kind != AstNode_Ident) {
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
continue;
}
@@ -1580,7 +1580,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
if (gd->flags & VarDeclFlag_thread_local) {
error_node(decl, "#thread_local variable declarations cannot have initialization values");
error(decl, "#thread_local variable declarations cannot have initialization values");
}
}
@@ -1592,7 +1592,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
value = vs->values[i];
}
if (name->kind != AstNode_Ident) {
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
continue;
}
Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, gd->token.kind == Token_let);
@@ -1601,7 +1601,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
if (gd->flags & VarDeclFlag_using) {
gd->flags &= ~VarDeclFlag_using; // NOTE(bill): This error will be only caught once
error_node(name, "`using` is not allowed at the file scope");
error(name, "`using` is not allowed at the file scope");
}
AstNode *fl = c->context.curr_foreign_library;
@@ -1636,7 +1636,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
AstNode *name = ts->name;
if (name->kind != AstNode_Ident) {
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
break;
}
@@ -1658,9 +1658,9 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
ast_node(ts, ImportSpec, spec);
if (!c->context.scope->is_file) {
if (ts->is_import) {
error_node(decl, "import declarations are only allowed in the file scope");
error(decl, "import declarations are only allowed in the file scope");
} else {
error_node(decl, "import_load declarations are only allowed in the file scope");
error(decl, "import_load declarations are only allowed in the file scope");
}
// NOTE(bill): _Should_ be caught by the parser
// TODO(bill): Better error handling if it isn't
@@ -1675,9 +1675,9 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
ast_node(fl, ForeignLibrarySpec, spec);
if (!c->context.scope->is_file) {
if (fl->is_system) {
error_node(spec, "foreign_system_library declarations are only allowed in the file scope");
error(spec, "foreign_system_library declarations are only allowed in the file scope");
} else {
error_node(spec, "foreign_library declarations are only allowed in the file scope");
error(spec, "foreign_library declarations are only allowed in the file scope");
}
// NOTE(bill): _Should_ be caught by the parser
// TODO(bill): Better error handling if it isn't
@@ -1688,7 +1688,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, fl->cond);
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
error_node(fl->cond, "Non-constant boolean `when` condition");
error(fl->cond, "Non-constant boolean `when` condition");
continue;
}
if (operand.value.kind == ExactValue_Bool &&
@@ -1707,7 +1707,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
case_ast_node(fb, ForeignBlockDecl, decl);
AstNode *foreign_library = fb->foreign_library;
if (foreign_library->kind != AstNode_Ident) {
error_node(foreign_library, "foreign library name must be an identifier");
error(foreign_library, "foreign library name must be an identifier");
foreign_library = NULL;
}
@@ -1720,7 +1720,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
case_ast_node(pd, ProcDecl, decl);
AstNode *name = pd->name;
if (name->kind != AstNode_Ident) {
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
break;
}
@@ -1743,7 +1743,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
default:
if (c->context.scope->is_file) {
error_node(decl, "Only declarations are allowed at file scope");
error(decl, "Only declarations are allowed at file scope");
}
break;
}
@@ -2011,7 +2011,7 @@ void check_import_entities(Checker *c, Map<Scope *> *file_scopes) {
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, id->cond);
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
error_node(id->cond, "Non-constant boolean `when` condition");
error(id->cond, "Non-constant boolean `when` condition");
continue;
}
if (operand.value.kind == ExactValue_Bool &&
@@ -2104,7 +2104,7 @@ void check_import_entities(Checker *c, Map<Scope *> *file_scopes) {
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, fl->cond);
if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) {
error_node(fl->cond, "Non-constant boolean `when` condition");
error(fl->cond, "Non-constant boolean `when` condition");
continue;
}
if (operand.value.kind == ExactValue_Bool &&
@@ -2116,7 +2116,7 @@ void check_import_entities(Checker *c, Map<Scope *> *file_scopes) {
String library_name = path_to_entity_name(fl->library_name.string, file_str);
if (library_name == "_") {
error_node(spec, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
error(spec, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
} else {
GB_ASSERT(fl->library_name.pos.line != 0);
fl->library_name.string = library_name;
+11
View File
@@ -2262,6 +2262,17 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
left = ir_emit_conv(proc, left, ir_type(right));
} else if (right->kind == irValue_Constant || right->kind == irValue_Nil) {
right = ir_emit_conv(proc, right, ir_type(left));
} else {
gbAllocator a = proc->module->allocator;
i64 ls = type_size_of(a, ir_type(left));
i64 rs = type_size_of(a, ir_type(right));
if (ls < rs) {
left = ir_emit_conv(proc, left, ir_type(right));
} else if (ls > rs) {
right = ir_emit_conv(proc, right, ir_type(left));
} else {
right = ir_emit_conv(proc, right, ir_type(left));
}
}
Type *result = t_bool;
+148 -148
View File
@@ -305,166 +305,166 @@ int main(int argc, char **argv) {
#endif
#if defined(GB_SYSTEM_WINDOWS)
timings_start_section(&timings, str_lit("llvm-llc"));
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = system_exec_command_line_app("llvm-llc", false,
"\"%.*sbin/llc\" \"%.*s.bc\" -filetype=obj -O%d "
"%.*s "
// "-debug-pass=Arguments "
"",
LIT(build_context.ODIN_ROOT),
LIT(output_base),
optimization_level,
LIT(build_context.llc_flags));
if (exit_code != 0) {
return exit_code;
}
timings_start_section(&timings, str_lit("llvm-llc"));
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = system_exec_command_line_app("llvm-llc", false,
"\"%.*sbin/llc\" \"%.*s.bc\" -filetype=obj -O%d "
"%.*s "
// "-debug-pass=Arguments "
"",
LIT(build_context.ODIN_ROOT),
LIT(output_base),
optimization_level,
LIT(build_context.llc_flags));
if (exit_code != 0) {
return exit_code;
}
timings_start_section(&timings, str_lit("msvc-link"));
timings_start_section(&timings, str_lit("msvc-link"));
gbString lib_str = gb_string_make(heap_allocator(), "");
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, ir_gen.module.foreign_library_paths) {
String lib = ir_gen.module.foreign_library_paths[i];
// gb_printf_err("Linking lib: %.*s\n", LIT(lib));
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" \"%.*s\"", LIT(lib));
lib_str = gb_string_appendc(lib_str, lib_str_buf);
}
char *output_ext = "exe";
char *link_settings = "";
if (build_context.is_dll) {
output_ext = "dll";
link_settings = "/DLL";
} else {
link_settings = "/ENTRY:mainCRTStartup";
}
exit_code = system_exec_command_line_app("msvc-link", true,
"link \"%.*s\".obj -OUT:\"%.*s.%s\" %s "
"/defaultlib:libcmt "
"/nologo /incremental:no /opt:ref /subsystem:CONSOLE "
" %.*s "
" %s "
"",
LIT(output_base), LIT(output_base), output_ext,
lib_str, LIT(build_context.link_flags),
link_settings
);
if (exit_code != 0) {
return exit_code;
}
// timings_print_all(&timings);
if (run_output) {
system_exec_command_line_app("odin run", false, "%.*s.exe", LIT(output_base));
}
#else
// NOTE(zangent): Linux / Unix is unfinished and not tested very well.
timings_start_section(&timings, str_lit("llvm-llc"));
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = system_exec_command_line_app("llc", false,
"llc \"%.*s.bc\" -filetype=obj -relocation-model=pic -O%d "
"%.*s "
// "-debug-pass=Arguments "
"",
LIT(output_base),
optimization_level,
LIT(build_context.llc_flags));
if (exit_code != 0) {
return exit_code;
}
timings_start_section(&timings, str_lit("ld-link"));
gbString lib_str = gb_string_make(heap_allocator(), "");
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, ir_gen.module.foreign_library_paths) {
String lib = ir_gen.module.foreign_library_paths[i];
// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
// This allows you to specify '-f' in a #foreign_system_library,
// without having to implement any new syntax specifically for MacOS.
#if defined(GB_SYSTEM_OSX)
isize len;
if(lib.len > 2 && lib[0] == '-' && lib[1] == 'f') {
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
} else {
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -l%.*s ", LIT(lib));
}
#else
gbString lib_str = gb_string_make(heap_allocator(), "");
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, ir_gen.module.foreign_library_paths) {
String lib = ir_gen.module.foreign_library_paths[i];
// gb_printf_err("Linking lib: %.*s\n", LIT(lib));
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -l%.*s ", LIT(lib));
#endif
lib_str = gb_string_appendc(lib_str, lib_str_buf);
}
" \"%.*s\"", LIT(lib));
lib_str = gb_string_appendc(lib_str, lib_str_buf);
}
// Unlike the Win32 linker code, the output_ext includes the dot, because
// typically executable files on *NIX systems don't have extensions.
char *output_ext = "";
char *link_settings = "";
char *linker;
if (build_context.is_dll) {
// Shared libraries are .dylib on MacOS and .so on Linux.
// TODO(zangent): Is that statement entirely truthful?
#if defined(GB_SYSTEM_OSX)
output_ext = ".dylib";
#else
output_ext = ".so";
#endif
char *output_ext = "exe";
char *link_settings = "";
if (build_context.is_dll) {
output_ext = "dll";
link_settings = "/DLL";
} else {
link_settings = "/ENTRY:mainCRTStartup";
}
link_settings = "-shared";
} else {
// TODO: Do I need anything here?
link_settings = "";
}
exit_code = system_exec_command_line_app("msvc-link", true,
"link \"%.*s\".obj -OUT:\"%.*s.%s\" %s "
"/defaultlib:libcmt "
"/nologo /incremental:no /opt:ref /subsystem:CONSOLE "
" %.*s "
" %s "
"",
LIT(output_base), LIT(output_base), output_ext,
lib_str, LIT(build_context.link_flags),
link_settings
);
if (exit_code != 0) {
return exit_code;
}
// timings_print_all(&timings);
if (run_output) {
system_exec_command_line_app("odin run", false, "%.*s.exe", LIT(output_base));
}
#if defined(GB_SYSTEM_OSX)
linker = "ld";
#else
// TODO(zangent): Figure out how to make ld work on Linux.
// It probably has to do with including the entire CRT, but
// that's quite a complicated issue to solve while remaining distro-agnostic.
// Clang can figure out linker flags for us, and that's good enough _for now_.
linker = "clang -Wno-unused-command-line-argument";
#endif
exit_code = system_exec_command_line_app("ld-link", true,
"%s \"%.*s\".o -o \"%.*s%s\" %s "
"-lc -lm "
" %.*s "
" %s "
// NOTE(zangent): Linux / Unix is unfinished and not tested very well.
timings_start_section(&timings, str_lit("llvm-llc"));
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = system_exec_command_line_app("llc", false,
"llc \"%.*s.bc\" -filetype=obj -relocation-model=pic -O%d "
"%.*s "
// "-debug-pass=Arguments "
"",
LIT(output_base),
optimization_level,
LIT(build_context.llc_flags));
if (exit_code != 0) {
return exit_code;
}
timings_start_section(&timings, str_lit("ld-link"));
gbString lib_str = gb_string_make(heap_allocator(), "");
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, ir_gen.module.foreign_library_paths) {
String lib = ir_gen.module.foreign_library_paths[i];
// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
// This allows you to specify '-f' in a #foreign_system_library,
// without having to implement any new syntax specifically for MacOS.
#if defined(GB_SYSTEM_OSX)
isize len;
if(lib.len > 2 && lib[0] == '-' && lib[1] == 'f') {
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
} else {
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -l%.*s ", LIT(lib));
}
#else
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -l%.*s ", LIT(lib));
#endif
lib_str = gb_string_appendc(lib_str, lib_str_buf);
}
// Unlike the Win32 linker code, the output_ext includes the dot, because
// typically executable files on *NIX systems don't have extensions.
char *output_ext = "";
char *link_settings = "";
char *linker;
if (build_context.is_dll) {
// Shared libraries are .dylib on MacOS and .so on Linux.
// TODO(zangent): Is that statement entirely truthful?
#if defined(GB_SYSTEM_OSX)
output_ext = ".dylib";
#else
output_ext = ".so";
#endif
link_settings = "-shared";
} else {
// TODO: Do I need anything here?
link_settings = "";
}
#if defined(GB_SYSTEM_OSX)
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
// make sure to also change the `mtriple` param passed to `opt`
" -macosx_version_min 10.8.0 "
// This points the linker to where the entry point is
" -e _main "
linker = "ld";
#else
// TODO(zangent): Figure out how to make ld work on Linux.
// It probably has to do with including the entire CRT, but
// that's quite a complicated issue to solve while remaining distro-agnostic.
// Clang can figure out linker flags for us, and that's good enough _for now_.
linker = "clang -Wno-unused-command-line-argument";
#endif
, linker, LIT(output_base), LIT(output_base), output_ext,
lib_str, LIT(build_context.link_flags),
link_settings
);
if (exit_code != 0) {
return exit_code;
}
// timings_print_all(&timings);
exit_code = system_exec_command_line_app("ld-link", true,
"%s \"%.*s\".o -o \"%.*s%s\" %s "
"-lc -lm "
" %.*s "
" %s "
#if defined(GB_SYSTEM_OSX)
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
// make sure to also change the `mtriple` param passed to `opt`
" -macosx_version_min 10.8.0 "
// This points the linker to where the entry point is
" -e _main "
#endif
, linker, LIT(output_base), LIT(output_base), output_ext,
lib_str, LIT(build_context.link_flags),
link_settings
);
if (exit_code != 0) {
return exit_code;
}
if (run_output) {
system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base));
}
// timings_print_all(&timings);
if (run_output) {
system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base));
}
#endif
#endif
+35 -32
View File
@@ -34,6 +34,7 @@ struct AstFile {
// NOTE(bill): Used to prevent type literals in control clauses
isize expr_level;
bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases
bool in_foreign_block;
Array<AstNode *> decls;
bool is_global_scope;
@@ -90,12 +91,11 @@ enum ProcTag {
};
enum ProcCallingConvention {
ProcCC_Odin = 0,
ProcCC_C = 1,
ProcCC_Std = 2,
ProcCC_Fast = 3,
ProcCC_Invalid,
ProcCC_Invalid = 0,
ProcCC_Odin = 1,
ProcCC_C = 2,
ProcCC_Std = 3,
ProcCC_Fast = 4,
};
enum VarDeclFlag {
@@ -861,21 +861,21 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
}
void error_node(AstNode *node, char *fmt, ...) {
void error(AstNode *node, char *fmt, ...) {
va_list va;
va_start(va, fmt);
error_va(ast_node_token(node), fmt, va);
va_end(va);
}
void warning_node(AstNode *node, char *fmt, ...) {
void warning(AstNode *node, char *fmt, ...) {
va_list va;
va_start(va, fmt);
warning_va(ast_node_token(node), fmt, va);
va_end(va);
}
void syntax_error_node(AstNode *node, char *fmt, ...) {
void syntax_error(AstNode *node, char *fmt, ...) {
va_list va;
va_start(va, fmt);
syntax_error_va(ast_node_token(node), fmt, va);
@@ -885,7 +885,7 @@ void syntax_error_node(AstNode *node, char *fmt, ...) {
bool ast_node_expect(AstNode *node, AstNodeKind kind) {
if (node->kind != kind) {
error_node(node, "Expected %.*s, got %.*s", LIT(ast_node_strings[node->kind]));
error(node, "Expected %.*s, got %.*s", LIT(ast_node_strings[node->kind]));
return false;
}
return true;
@@ -1980,7 +1980,7 @@ AstNode *parse_type_or_ident(AstFile *f);
void check_proc_add_tag(AstFile *f, AstNode *tag_expr, u64 *tags, ProcTag tag, String tag_name) {
if (*tags & tag) {
syntax_error_node(tag_expr, "Procedure tag already used: %.*s", LIT(tag_name));
syntax_error(tag_expr, "Procedure tag already used: %.*s", LIT(tag_name));
}
*tags |= tag;
}
@@ -2056,7 +2056,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
*link_name = f->curr_token.string;
// TODO(bill): Check if valid string
if (!is_foreign_name_valid(*link_name)) {
syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name));
syntax_error(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name));
}
next_token(f);
@@ -2076,35 +2076,35 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
if (cc == ProcCC_Invalid) {
cc = ProcCC_Odin;
} else {
syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
syntax_error(tag_expr, "Multiple calling conventions for procedure type");
}
} else if (tag_name == "cc_c") {
if (cc == ProcCC_Invalid) {
cc = ProcCC_C;
} else {
syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
syntax_error(tag_expr, "Multiple calling conventions for procedure type");
}
} else if (tag_name == "cc_std") {
if (cc == ProcCC_Invalid) {
cc = ProcCC_Std;
} else {
syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
syntax_error(tag_expr, "Multiple calling conventions for procedure type");
}
} else if (tag_name == "cc_fast") {
if (cc == ProcCC_Invalid) {
cc = ProcCC_Fast;
} else {
syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
syntax_error(tag_expr, "Multiple calling conventions for procedure type");
}
} else {
syntax_error_node(tag_expr, "Unknown procedure tag #%.*s\n", LIT(tag_name));
syntax_error(tag_expr, "Unknown procedure tag #%.*s\n", LIT(tag_name));
}
#undef ELSE_IF_ADD_TAG
}
if (cc == ProcCC_Invalid) {
if ((*tags) & ProcTag_foreign) {
if ((*tags) & ProcTag_foreign || f->in_foreign_block) {
cc = ProcCC_C;
} else {
cc = ProcCC_Odin;
@@ -2116,7 +2116,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
}
if ((*tags & ProcTag_foreign) && (*tags & ProcTag_export)) {
syntax_error(f->curr_token, "You cannot apply both #foreign and #export to a procedure");
syntax_error(f->curr_token, "A foreign procedure cannot have #export");
}
if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) {
@@ -2221,7 +2221,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
AstNode *expr = parse_expr(f, false);
operand = ast_run_expr(f, token, name, expr);
if (unparen_expr(expr)->kind != AstNode_CallExpr) {
error_node(expr, "#run can only be applied to procedure calls");
error(expr, "#run can only be applied to procedure calls");
operand = ast_bad_expr(f, token, f->curr_token);
}
warning(token, "#run is not yet implemented");
@@ -2943,7 +2943,7 @@ void parse_foreign_block_decl(AstFile *f, Array<AstNode *> *decls) {
/* fallthrough */
default:
error_node(decl, "Foreign blocks only allow procedure and variable declarations");
error(decl, "Foreign blocks only allow procedure and variable declarations");
return;
}
}
@@ -2979,6 +2979,10 @@ AstNode *parse_decl(AstFile *f) {
Token close = {};
Array<AstNode *> decls = make_ast_node_array(f);
bool prev_in_foreign_block = f->in_foreign_block;
defer (f->in_foreign_block = prev_in_foreign_block);
f->in_foreign_block = true;
if (f->curr_token.kind != Token_OpenBrace) {
parse_foreign_block_decl(f, &decls);
} else {
@@ -3161,8 +3165,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
u64 tags = 0;
String link_name = {};
ProcCallingConvention cc = ProcCC_Odin;
ProcCallingConvention cc = ProcCC_Invalid;
parse_proc_tags(f, &tags, &link_name, &cc);
if (link_name_) *link_name_ = link_name;
@@ -3293,7 +3296,7 @@ Array<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list,
if (!ignore_flags) {
if (i != 0) {
error_node(ident, "Illegal use of prefixes in parameter list");
error(ident, "Illegal use of prefixes in parameter list");
}
}
@@ -3302,7 +3305,7 @@ Array<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list,
case AstNode_BadExpr:
break;
default:
error_node(ident, "Expected an identifier");
error(ident, "Expected an identifier");
ident = ast_ident(f, blank_token);
break;
}
@@ -3951,7 +3954,7 @@ AstNode *parse_for_stmt(AstFile *f) {
index = cond->AssignStmt.lhs[1];
break;
default:
error_node(cond, "Expected at 1 or 2 identifiers");
error(cond, "Expected at 1 or 2 identifiers");
return ast_bad_stmt(f, token, f->curr_token);
}
@@ -4301,7 +4304,7 @@ Array<AstNode *> parse_stmt_list(AstFile *f) {
if (stmt->kind == AstNode_ExprStmt &&
stmt->ExprStmt.expr != NULL &&
stmt->ExprStmt.expr->kind == AstNode_ProcLit) {
syntax_error_node(stmt, "Procedure literal evaluated but not used");
syntax_error(stmt, "Procedure literal evaluated but not used");
}
}
}
@@ -4466,7 +4469,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
node->kind != AstNode_BadStmt &&
node->kind != AstNode_EmptyStmt) {
// NOTE(bill): Sanity check
syntax_error_node(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind]));
syntax_error(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind]));
} else if (node->kind == AstNode_GenDecl) {
ast_node(gd, GenDecl, node);
if (gd->token.kind == Token_import ||
@@ -4482,9 +4485,9 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
if (!is_import_path_valid(file_str)) {
if (id->is_import) {
syntax_error_node(node, "Invalid import path: `%.*s`", LIT(file_str));
syntax_error(node, "Invalid import path: `%.*s`", LIT(file_str));
} else {
syntax_error_node(node, "Invalid include path: `%.*s`", LIT(file_str));
syntax_error(node, "Invalid include path: `%.*s`", LIT(file_str));
}
// NOTE(bill): It's a naughty name
decls[i] = ast_bad_decl(f, id->relpath, id->relpath);
@@ -4513,9 +4516,9 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
if (!is_import_path_valid(file_str)) {
if (fl->is_system) {
syntax_error_node(node, "Invalid `foreign_system_library` path");
syntax_error(node, "Invalid `foreign_system_library` path");
} else {
syntax_error_node(node, "Invalid `foreign_library` path");
syntax_error(node, "Invalid `foreign_library` path");
}
// NOTE(bill): It's a naughty name
gd->specs[spec_index] = ast_bad_decl(f, fl->filepath, fl->filepath);