aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-12-09 00:07:08 +0000
committerGinger Bill <bill@gingerbill.org>2016-12-09 00:07:08 +0000
commit0d69dfcde6baea4fba80d2456986a00c072ad5c9 (patch)
tree5c8e57736b8184bd7f099b4eecbfa8a1c8718955 /src
parentfa89d2775a61b1e6943909ff5c96a1e01892d8c9 (diff)
Custom entry points on Windows (DllMain; WinMain)
Diffstat (limited to 'src')
-rw-r--r--src/checker/decl.c49
-rw-r--r--src/checker/entity.c2
-rw-r--r--src/main.c6
-rw-r--r--src/parser.c50
-rw-r--r--src/ssa.c145
-rw-r--r--src/ssa_print.c65
6 files changed, 208 insertions, 109 deletions
diff --git a/src/checker/decl.c b/src/checker/decl.c
index e2dd71daf..134bfb87b 100644
--- a/src/checker/decl.c
+++ b/src/checker/decl.c
@@ -309,7 +309,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
check_procedure_type(c, proc_type, pd->type);
bool is_foreign = (pd->tags & ProcTag_foreign) != 0;
- bool is_export = (pd->tags & ProcTag_export) != 0;
+ bool is_link_name = (pd->tags & ProcTag_link_name) != 0;
+ bool is_export = (pd->tags & ProcTag_export) != 0;
bool is_inline = (pd->tags & ProcTag_inline) != 0;
bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
@@ -330,10 +331,13 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
}
- if (is_foreign && is_export) {
- error_node(pd->type, "You cannot apply both `foreign` and `export_name` to a procedure");
+ if (is_foreign && is_link_name) {
+ error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure");
+ } else if (is_foreign && is_export) {
+ error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure");
}
+
if (pd->body != NULL) {
if (is_foreign) {
error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body");
@@ -372,24 +376,31 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
} else {
map_entity_set(fp, key, e);
}
- } else if (is_export) {
- MapEntity *fp = &c->info.foreign_procs;
- AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl;
- String name = proc_decl->export_name;
+ } else {
+ String name = e->token.string;
+ if (is_link_name) {
+ AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl;
+ name = proc_decl->link_name;
+ }
- e->Procedure.export_name = name;
+ if (is_link_name || is_export) {
+ MapEntity *fp = &c->info.foreign_procs;
- HashKey key = hash_string(name);
- Entity **found = map_entity_get(fp, key);
- if (found) {
- Entity *f = *found;
- TokenPos pos = f->token.pos;
- error_node(d->proc_decl,
- "Non unique #export name for procedure `%.*s`\n"
- "\tother at %.*s(%td:%td)",
- LIT(name), LIT(pos.file), pos.line, pos.column);
- } else {
- map_entity_set(fp, key, e);
+ e->Procedure.link_name = name;
+
+ HashKey key = hash_string(name);
+ Entity **found = map_entity_get(fp, key);
+ if (found) {
+ Entity *f = *found;
+ TokenPos pos = f->token.pos;
+ // TODO(bill): Better error message?
+ error_node(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);
+ } else {
+ map_entity_set(fp, key, e);
+ }
}
}
diff --git a/src/checker/entity.c b/src/checker/entity.c
index db335dabb..9da334ea8 100644
--- a/src/checker/entity.c
+++ b/src/checker/entity.c
@@ -62,7 +62,7 @@ struct Entity {
struct {
bool is_foreign;
String foreign_name;
- String export_name;
+ String link_name;
u64 tags;
} Procedure;
struct {
diff --git a/src/main.c b/src/main.c
index 480d42397..a9f3c6d6b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -29,8 +29,8 @@ i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
start_info.wShowWindow = SW_SHOW;
start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- start_info.hStdOutput = is_silent ? NULL : GetStdHandle(STD_OUTPUT_HANDLE);
- start_info.hStdError = is_silent ? NULL : GetStdHandle(STD_ERROR_HANDLE);
+ start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
va_start(va, fmt);
cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
@@ -232,7 +232,7 @@ int main(int argc, char **argv) {
exit_code = win32_exec_command_line_app("msvc-link", true,
"link %.*s.obj -OUT:%.*s.%s %s "
"/defaultlib:libcmt "
- "/nologo /incremental:no /opt:ref /subsystem:console "
+ "/nologo /incremental:no /opt:ref /subsystem:WINDOWS "
" %.*s "
" %s "
"",
diff --git a/src/parser.c b/src/parser.c
index 708d336ed..6b09b9da6 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -66,10 +66,11 @@ typedef enum ProcTag {
ProcTag_foreign = GB_BIT(10),
ProcTag_export = GB_BIT(11),
- ProcTag_inline = GB_BIT(12),
- ProcTag_no_inline = GB_BIT(13),
- ProcTag_dll_import = GB_BIT(14),
- ProcTag_dll_export = GB_BIT(15),
+ ProcTag_link_name = GB_BIT(12),
+ ProcTag_inline = GB_BIT(13),
+ ProcTag_no_inline = GB_BIT(14),
+ ProcTag_dll_import = GB_BIT(15),
+ // ProcTag_dll_export = GB_BIT(16),
ProcTag_stdcall = GB_BIT(20),
ProcTag_fastcall = GB_BIT(21),
@@ -106,7 +107,7 @@ AstNodeArray make_ast_node_array(AstFile *f) {
AstNode *body; \
u64 tags; \
String foreign_name; \
- String export_name; \
+ String link_name; \
}) \
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
AstNode *type; \
@@ -246,7 +247,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
AstNode *body; \
u64 tags; \
String foreign_name; \
- String export_name; \
+ String link_name; \
AstNode *note; \
}) \
AST_NODE_KIND(TypeDecl, "type declaration", struct { \
@@ -686,13 +687,13 @@ AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) {
}
-AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String foreign_name, String export_name) {
+AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String foreign_name, String link_name) {
AstNode *result = make_node(f, AstNode_ProcLit);
result->ProcLit.type = type;
result->ProcLit.body = body;
result->ProcLit.tags = tags;
result->ProcLit.foreign_name = foreign_name;
- result->ProcLit.export_name = export_name;
+ result->ProcLit.link_name = link_name;
return result;
}
@@ -926,14 +927,14 @@ AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArr
return result;
}
-AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String export_name) {
+AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) {
AstNode *result = make_node(f, AstNode_ProcDecl);
result->ProcDecl.name = name;
result->ProcDecl.type = proc_type;
result->ProcDecl.body = body;
result->ProcDecl.tags = tags;
result->ProcDecl.foreign_name = foreign_name;
- result->ProcDecl.export_name = export_name;
+ result->ProcDecl.link_name = link_name;
return result;
}
@@ -1364,10 +1365,10 @@ bool is_foreign_name_valid(String name) {
return true;
}
-void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export_name) {
+void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name) {
// TODO(bill): Add this to procedure literals too
GB_ASSERT(foreign_name != NULL);
- GB_ASSERT(export_name != NULL);
+ GB_ASSERT(link_name != NULL);
while (f->curr_token.kind == Token_Hash) {
AstNode *tag_expr = parse_tag_expr(f, NULL);
@@ -1390,13 +1391,13 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export
next_token(f);
}
- } else if (str_eq(tag_name, str_lit("export"))) {
- check_proc_add_tag(f, tag_expr, tags, ProcTag_export, tag_name);
+ } else if (str_eq(tag_name, str_lit("link_name"))) {
+ check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
if (f->curr_token.kind == Token_String) {
- *export_name = f->curr_token.string;
+ *link_name = f->curr_token.string;
// TODO(bill): Check if valid string
- if (!is_foreign_name_valid(*export_name)) {
- syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*export_name));
+ if (!is_foreign_name_valid(*link_name)) {
+ syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name));
}
next_token(f);
@@ -1404,12 +1405,13 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *export
expect_token(f, Token_String);
}
}
+ ELSE_IF_ADD_TAG(export)
ELSE_IF_ADD_TAG(bounds_check)
ELSE_IF_ADD_TAG(no_bounds_check)
ELSE_IF_ADD_TAG(inline)
ELSE_IF_ADD_TAG(no_inline)
ELSE_IF_ADD_TAG(dll_import)
- ELSE_IF_ADD_TAG(dll_export)
+ // ELSE_IF_ADD_TAG(dll_export)
ELSE_IF_ADD_TAG(stdcall)
ELSE_IF_ADD_TAG(fastcall)
// ELSE_IF_ADD_TAG(cdecl)
@@ -1534,8 +1536,8 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
u64 tags = 0;
String foreign_name = {0};
- String export_name = {0};
- parse_proc_tags(f, &tags, &foreign_name, &export_name);
+ String link_name = {0};
+ parse_proc_tags(f, &tags, &foreign_name, &link_name);
if (tags & ProcTag_foreign) {
syntax_error(f->curr_token, "#foreign cannot be applied to procedure literals");
}
@@ -1551,7 +1553,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
}
body = parse_body(f);
- type = make_proc_lit(f, type, body, tags, foreign_name, export_name);
+ type = make_proc_lit(f, type, body, tags, foreign_name, link_name);
} else if (type != NULL && type->kind == AstNode_ProcType) {
type->ProcType.tags = tags;
}
@@ -2426,9 +2428,9 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
AstNode *body = NULL;
u64 tags = 0;
String foreign_name = {0};
- String export_name = {0};
+ String link_name = {0};
- parse_proc_tags(f, &tags, &foreign_name, &export_name);
+ parse_proc_tags(f, &tags, &foreign_name, &link_name);
AstNode *curr_proc = f->curr_proc;
f->curr_proc = proc_type;
@@ -2443,7 +2445,7 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
}
f->curr_proc = curr_proc;
- return make_proc_decl(f, name, proc_type, body, tags, foreign_name, export_name);
+ return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
}
AstNode *parse_if_stmt(AstFile *f) {
diff --git a/src/ssa.c b/src/ssa.c
index 89fd46d0d..e4b8a8e84 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -39,6 +39,8 @@ typedef struct ssaModule {
i32 global_string_index;
i32 global_array_index; // For ConstantSlice
+ Entity * entry_point_entity;
+
Array(ssaProcedure *) procs; // NOTE(bill): All procedures with bodies
ssaValueArray procs_to_generate; // NOTE(bill): Procedures to generate
} ssaModule;
@@ -97,7 +99,6 @@ typedef struct ssaDefer {
};
} ssaDefer;
-typedef struct ssaProcedure ssaProcedure;
struct ssaProcedure {
ssaProcedure * parent;
Array(ssaProcedure *) children;
@@ -110,7 +111,7 @@ struct ssaProcedure {
AstNode * body;
u64 tags;
- ssaValueArray params;
+ ssaValueArray params;
Array(ssaDefer) defer_stmts;
Array(ssaBlock *) blocks;
i32 scope_index;
@@ -118,7 +119,7 @@ struct ssaProcedure {
ssaBlock * entry_block;
ssaBlock * curr_block;
ssaTargetList * target_list;
- ssaValueArray referrers;
+ ssaValueArray referrers;
i32 local_count;
i32 instr_count;
@@ -3930,8 +3931,8 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
// parent.name-guid
String original_name = pd->name->Ident.string;
String pd_name = original_name;
- if (pd->export_name.len > 0) {
- pd_name = pd->export_name;
+ if (pd->link_name.len > 0) {
+ pd_name = pd->link_name;
}
isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
@@ -4571,8 +4572,11 @@ void ssa_begin_procedure_body(ssaProcedure *proc) {
TypeTuple *params = &proc->type->Proc.params->Tuple;
for (isize i = 0; i < params->variable_count; i++) {
Entity *e = params->variables[i];
- ssaValue *param = ssa_add_param(proc, e);
- array_add(&proc->params, param);
+ if (!str_eq(e->token.string, str_lit("")) &&
+ !str_eq(e->token.string, str_lit("_"))) {
+ ssaValue *param = ssa_add_param(proc, e);
+ array_add(&proc->params, param);
+ }
}
}
}
@@ -4857,6 +4861,8 @@ void ssa_gen_tree(ssaGen *s) {
isize global_variable_max_count = 0;
Entity *entry_point = NULL;
+ bool has_dll_main = false;
+ bool has_win_main = false;
for_array(i, info->entities.entries) {
MapDeclInfoEntry *entry = &info->entities.entries.e[i];
@@ -4864,10 +4870,18 @@ void ssa_gen_tree(ssaGen *s) {
String name = e->token.string;
if (e->kind == Entity_Variable) {
global_variable_max_count++;
- } else if (e->kind == Entity_Procedure) {
+ } else if (e->kind == Entity_Procedure && !e->scope->is_global) {
if (e->scope->is_init && str_eq(name, str_lit("main"))) {
entry_point = e;
- break;
+ }
+ if ((e->Procedure.tags & ProcTag_export) != 0 ||
+ (e->Procedure.link_name.len > 0) ||
+ (e->scope->is_file && e->Procedure.link_name.len > 0)) {
+ if (!has_dll_main && str_eq(name, str_lit("DllMain"))) {
+ has_dll_main = true;
+ } else if (!has_win_main && str_eq(name, str_lit("WinMain"))) {
+ has_win_main = true;
+ }
}
}
}
@@ -4879,6 +4893,7 @@ void ssa_gen_tree(ssaGen *s) {
Array(ssaGlobalVariable) global_variables;
array_init_reserve(&global_variables, m->tmp_allocator, global_variable_max_count);
+ m->entry_point_entity = entry_point;
m->min_dep_map = generate_minimum_dependency_map(info, entry_point);
for_array(i, info->entities.entries) {
@@ -4897,8 +4912,13 @@ void ssa_gen_tree(ssaGen *s) {
continue;
}
- if (!scope->is_global && !scope->is_init) {
- name = ssa_mangle_name(s, e->token.pos.file, name);
+ if (!scope->is_global) {
+ if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
+ } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
+ } else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) {
+ } else {
+ name = ssa_mangle_name(s, e->token.pos.file, name);
+ }
}
@@ -4947,8 +4967,8 @@ void ssa_gen_tree(ssaGen *s) {
}
if (pd->foreign_name.len > 0) {
name = pd->foreign_name;
- } else if (pd->export_name.len > 0) {
- name = pd->export_name;
+ } else if (pd->link_name.len > 0) {
+ name = pd->link_name;
}
ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
@@ -4999,7 +5019,93 @@ void ssa_gen_tree(ssaGen *s) {
}
}
+#if defined(GB_SYSTEM_WINDOWS)
+ if (m->build_context->is_dll && !has_dll_main) {
+ // DllMain :: proc(inst: rawptr, reason: u32, reserved: rawptr) -> i32
+ String name = str_lit("DllMain");
+ Type *proc_params = make_type_tuple(a);
+ Type *proc_results = make_type_tuple(a);
+
+ Scope *proc_scope = gb_alloc_item(a, Scope);
+
+ proc_params->Tuple.variables = gb_alloc_array(a, Entity *, 3);
+ proc_params->Tuple.variable_count = 3;
+
+ proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1);
+ proc_results->Tuple.variable_count = 1;
+
+ proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false);
+ proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, blank_token, t_u32, false);
+ proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false);
+
+ proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false);
+
+
+ Type *proc_type = make_type_proc(a, proc_scope,
+ proc_params, 3,
+ proc_results, 1, false);
+
+ AstNode *body = gb_alloc_item(a, AstNode);
+ Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0);
+ ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name);
+
+ map_ssa_value_set(&m->values, hash_pointer(e), p);
+ map_ssa_value_set(&m->members, hash_string(name), p);
+
+ ssaProcedure *proc = &p->Proc;
+ proc->tags = ProcTag_no_inline | ProcTag_stdcall; // TODO(bill): is no_inline a good idea?
+ e->Procedure.link_name = name;
+
+ ssa_begin_procedure_body(proc);
+ ssa_emit_global_call(proc, "main", NULL, 0);
+ ssa_emit_return(proc, v_one32);
+ ssa_end_procedure_body(proc);
+ }
+#endif
+#if defined(GB_SYSTEM_WINDOWS)
+ if (!m->build_context->is_dll && !has_win_main) {
+ // WinMain :: proc(inst, prev: rawptr, cmd_line: ^byte, cmd_show: i32) -> i32
+ String name = str_lit("WinMain");
+ Type *proc_params = make_type_tuple(a);
+ Type *proc_results = make_type_tuple(a);
+
+ Scope *proc_scope = gb_alloc_item(a, Scope);
+
+ proc_params->Tuple.variables = gb_alloc_array(a, Entity *, 4);
+ proc_params->Tuple.variable_count = 4;
+
+ proc_results->Tuple.variables = gb_alloc_array(a, Entity *, 1);
+ proc_results->Tuple.variable_count = 1;
+
+ proc_params->Tuple.variables[0] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false);
+ proc_params->Tuple.variables[1] = make_entity_param(a, proc_scope, blank_token, t_rawptr, false);
+ proc_params->Tuple.variables[2] = make_entity_param(a, proc_scope, blank_token, t_u8_ptr, false);
+ proc_params->Tuple.variables[3] = make_entity_param(a, proc_scope, blank_token, t_i32, false);
+
+ proc_results->Tuple.variables[0] = make_entity_param(a, proc_scope, empty_token, t_i32, false);
+
+
+ Type *proc_type = make_type_proc(a, proc_scope,
+ proc_params, 4,
+ proc_results, 1, false);
+
+ AstNode *body = gb_alloc_item(a, AstNode);
+ Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0);
+ ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name);
+
+ map_ssa_value_set(&m->values, hash_pointer(e), p);
+ map_ssa_value_set(&m->members, hash_string(name), p);
+
+ ssaProcedure *proc = &p->Proc;
+ proc->tags = ProcTag_no_inline | ProcTag_stdcall; // TODO(bill): is no_inline a good idea?
+ e->Procedure.link_name = name;
+ ssa_begin_procedure_body(proc);
+ ssa_emit_global_call(proc, "main", NULL, 0);
+ ssa_emit_return(proc, v_one32);
+ ssa_end_procedure_body(proc);
+ }
+#endif
{ // Startup Runtime
// Cleanup(bill): probably better way of doing code insertion
String name = str_lit(SSA_STARTUP_RUNTIME_PROC_NAME);
@@ -5007,10 +5113,8 @@ void ssa_gen_tree(ssaGen *s) {
NULL, 0,
NULL, 0, false);
AstNode *body = gb_alloc_item(a, AstNode);
- ssaValue *p = ssa_make_value_procedure(a, m, NULL, proc_type, NULL, body, name);
- Token token = {0};
- token.string = name;
- Entity *e = make_entity_procedure(a, NULL, token, proc_type, 0);
+ Entity *e = make_entity_procedure(a, NULL, make_token_ident(name), proc_type, 0);
+ ssaValue *p = ssa_make_value_procedure(a, m, e, proc_type, NULL, body, name);
map_ssa_value_set(&m->values, hash_pointer(e), p);
map_ssa_value_set(&m->members, hash_string(name), p);
@@ -5431,13 +5535,6 @@ void ssa_gen_tree(ssaGen *s) {
ssa_build_proc(m->procs_to_generate.e[i], m->procs_to_generate.e[i]->Proc.parent);
}
- // {
- // DWORD old_protect = 0;
- // DWORD new_protect = PAGE_READONLY;
- // BOOL ok = VirtualProtect(m->arena.physical_start, m->arena.total_size, new_protect, &old_protect);
- // }
-
-
// m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
}
diff --git a/src/ssa_print.c b/src/ssa_print.c
index a1eee845a..17ec1c9b1 100644
--- a/src/ssa_print.c
+++ b/src/ssa_print.c
@@ -127,9 +127,9 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) {
ssa_print_escape_string(f, name, true);
}
-void ssa_print_encoded_global(ssaFileBuffer *f, String name, bool global_scope) {
+void ssa_print_encoded_global(ssaFileBuffer *f, String name, bool remove_prefix) {
ssa_fprintf(f, "@");
- if (!global_scope && str_ne(name, str_lit("main"))) {
+ if (!remove_prefix) {
ssa_fprintf(f, ".");
}
ssa_print_escape_string(f, name, true);
@@ -567,6 +567,20 @@ void ssa_print_block_name(ssaFileBuffer *f, ssaBlock *b) {
}
}
+bool ssa_print_is_proc_global(ssaModule *m, ssaProcedure *proc) {
+ if (proc->entity != NULL &&
+ proc->entity->kind == Entity_Procedure) {
+ if (m->entry_point_entity == proc->entity) {
+ // TODO(bill): This may not be needed during windows
+ return true;
+ }
+ if (proc->entity->Procedure.link_name.len > 0) {
+ return true;
+ }
+ }
+ return (proc->tags & (ProcTag_foreign|ProcTag_export)) != 0;
+}
+
void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint) {
if (value == NULL) {
ssa_fprintf(f, "!!!NULL_VALUE");
@@ -623,7 +637,7 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
ssa_print_encoded_local(f, value->Param.entity->token.string);
break;
case ssaValue_Proc:
- ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & (ProcTag_foreign|ProcTag_export)) != 0);
+ ssa_print_encoded_global(f, value->Proc.name, ssa_print_is_proc_global(m, &value->Proc));
break;
case ssaValue_Instr:
ssa_fprintf(f, "%%%d", value->index);
@@ -1229,10 +1243,11 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
} else {
ssa_fprintf(f, "\n");
ssa_fprintf(f, "define ");
- if (proc->tags & ProcTag_export) {
- ssa_fprintf(f, "dllexport ");
- } else if (proc->tags & ProcTag_dll_export) {
- ssa_fprintf(f, "dllexport ");
+ if (m->build_context->is_dll) {
+ // if (proc->tags & (ProcTag_export|ProcTag_dll_export)) {
+ if (proc->tags & (ProcTag_export)) {
+ ssa_fprintf(f, "dllexport ");
+ }
}
}
@@ -1251,7 +1266,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
}
ssa_fprintf(f, " ");
- ssa_print_encoded_global(f, proc->name, (proc->tags & (ProcTag_foreign|ProcTag_export)) != 0);
+ ssa_print_encoded_global(f, proc->name, ssa_print_is_proc_global(m, proc));
ssa_fprintf(f, "(");
if (proc_type->param_count > 0) {
@@ -1263,7 +1278,10 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
}
ssa_print_type(f, m, e->type);
if (proc->body != NULL) {
- ssa_fprintf(f, " %%%.*s", LIT(e->token.string));
+ if (!str_eq(e->token.string, str_lit("")) &&
+ !str_eq(e->token.string, str_lit("_"))) {
+ ssa_fprintf(f, " %%%.*s", LIT(e->token.string));
+ }
}
}
}
@@ -1369,12 +1387,6 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
continue;
}
-#if defined(GB_SYSTEM_WINDOWS)
- if (str_eq(v->Proc.name, str_lit("DllMain"))) {
- dll_main_found = true;
- }
-#endif
-
if (v->Proc.body == NULL) {
ssa_print_proc(f, m, &v->Proc);
}
@@ -1387,34 +1399,11 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
continue;
}
-#if defined(GB_SYSTEM_WINDOWS)
- if (str_eq(v->Proc.name, str_lit("DllMain"))) {
- dll_main_found = true;
- }
-#endif
-
if (v->Proc.body != NULL) {
ssa_print_proc(f, m, &v->Proc);
}
}
- if (m->build_context->is_dll) {
-#if !defined(GB_SYSTEM_WINDOWS)
-#error Setup dll initialization on linux if appropriate
-#else
- if (!dll_main_found) {
- ssa_fprintf(f,
- "define i32 @DllMain(%%..rawptr %%inst, i32 %%reason, %%..rawptr %%reserved) {\n"
- "entry:\n"
- " call void @main()\n"
- " ret i32 1\n"
- "}\n"
- );
- }
-#endif
- }
-
-
for_array(member_index, m->members.entries) {
MapSsaValueEntry *entry = &m->members.entries.e[member_index];
ssaValue *v = entry->value;