Skip to content

Commit

Permalink
Custom entry points on Windows (DllMain; WinMain)
Browse files Browse the repository at this point in the history
  • Loading branch information
gingerBill committed Dec 9, 2016
1 parent fa89d27 commit 0d69dfc
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 114 deletions.
2 changes: 1 addition & 1 deletion build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ rem pushd %build_dir%

cl %compiler_settings% "src\main.c" ^
/link %linker_settings% -OUT:%exe_name% ^
&& odin build_dll code/example.odin ^
&& odin run code/demo.odin
rem && odin build_dll code/example.odin ^
rem && odin run code/demo.odin


Expand Down
2 changes: 2 additions & 0 deletions code/demo.odin
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ main :: proc() {
}
defer win32.FreeLibrary(lib)


proc_handle := get_proc(lib, "some_thing")
if proc_handle == nil {
fmt.println("Could not load 'some_thing'")
return
}

some_thing := (proc_handle as proc())
fmt.println(some_thing)
some_thing()
}
8 changes: 4 additions & 4 deletions core/mem.odin
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#import "fmt.odin"
#import "os.odin"

set :: proc(data: rawptr, value: i32, len: int) -> rawptr #export "__mem_set" {
set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" {
llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign "llvm.memset.p0i8.i64"
llvm_memset_64bit(data, value as byte, len, 1, false)
return data
Expand All @@ -11,22 +11,22 @@ zero :: proc(data: rawptr, len: int) -> rawptr {
return set(data, 0, len)
}

copy :: proc(dst, src: rawptr, len: int) -> rawptr #export "__mem_copy" {
copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" {
// NOTE(bill): This _must_ implemented like C's memmove
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
llvm_memmove_64bit(dst, src, len, 1, false)
return dst
}

copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #export "__mem_copy_non_overlapping" {
copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" {
// NOTE(bill): This _must_ implemented like C's memcpy
llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memcpy.p0i8.p0i8.i64"
llvm_memcpy_64bit(dst, src, len, 1, false)
return dst
}


compare :: proc(dst, src: rawptr, n: int) -> int #export "__mem_compare" {
compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
// Translation of http://mgronhol.github.io/fast-strcmp/
a := slice_ptr(dst as ^byte, n)
b := slice_ptr(src as ^byte, n)
Expand Down
49 changes: 30 additions & 19 deletions src/checker/decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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");
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/checker/entity.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ struct Entity {
struct {
bool is_foreign;
String foreign_name;
String export_name;
String link_name;
u64 tags;
} Procedure;
struct {
Expand Down
6 changes: 3 additions & 3 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 "
"",
Expand Down
50 changes: 26 additions & 24 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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; \
Expand Down Expand Up @@ -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 { \
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -1390,26 +1391,27 @@ 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);
} else {
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)
Expand Down Expand Up @@ -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");
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
Loading

0 comments on commit 0d69dfc

Please sign in to comment.