Skip to content

Commit

Permalink
Specify WASM import module name by __attribute__
Browse files Browse the repository at this point in the history
  * Keep attributes in `Table`
  * Use for WASI module functions
  • Loading branch information
tyfkda committed Feb 21, 2024
1 parent 095656c commit 64d4e1e
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 63 deletions.
36 changes: 19 additions & 17 deletions libsrc/_wasm/wasi.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <stddef.h> // size_t
#include <stdint.h>

#define WASI_MODULE __attribute__((import_module("wasi_snapshot_preview1")))

// Fdflags
#define FDFLAGS_APPEND (1 << 0)
#define FDFLAGS_DSYNC (1 << 1)
Expand Down Expand Up @@ -97,25 +99,25 @@ enum Filetype {
FILETYPE_SYMBOLIC_LINK,
};

int args_sizes_get(int *pargc, int *plen);
int args_get(char **pargv, char *pstr);
void proc_exit(int) __attribute__((noreturn));
WASI_MODULE int args_sizes_get(int *pargc, int *plen);
WASI_MODULE int args_get(char **pargv, char *pstr);
WASI_MODULE void proc_exit(int) __attribute__((noreturn));

int fd_prestat_get(int fd, Prestat *prestat);
int fd_prestat_dir_name(int fd, char *out, size_t size);
WASI_MODULE int fd_prestat_get(int fd, Prestat *prestat);
WASI_MODULE int fd_prestat_dir_name(int fd, char *out, size_t size);

int path_open(int fd, int dirflags, const char *path, size_t path_len, int oflags,
uint64_t fs_rights_base, uint64_t fs_rights_inherting, uint16_t fdflags,
uint32_t *opend_fd);
int path_unlink_file(int fd, const char *path, size_t path_len);
int path_filestat_get(int fd, int flags, const char *path, size_t path_len, Filestat *out);
WASI_MODULE int path_open(int fd, int dirflags, const char *path, size_t path_len, int oflags,
uint64_t fs_rights_base, uint64_t fs_rights_inherting, uint16_t fdflags,
uint32_t *opend_fd);
WASI_MODULE int path_unlink_file(int fd, const char *path, size_t path_len);
WASI_MODULE int path_filestat_get(int fd, int flags, const char *path, size_t path_len, Filestat *out);

int fd_read(int fd, const void *iov, int count, size_t *out);
int fd_write(int fd, const void *iov, int count, size_t *out);
int fd_close(int fd);
int fd_seek(int fd, int64_t offset, int whence, size_t *psize);
int fd_filestat_get(int fd, Filestat *out);
WASI_MODULE int fd_read(int fd, const void *iov, int count, size_t *out);
WASI_MODULE int fd_write(int fd, const void *iov, int count, size_t *out);
WASI_MODULE int fd_close(int fd);
WASI_MODULE int fd_seek(int fd, int64_t offset, int whence, size_t *psize);
WASI_MODULE int fd_filestat_get(int fd, Filestat *out);

int clock_time_get(int clockid, uint64_t precision, uint64_t *out);
WASI_MODULE int clock_time_get(int clockid, uint64_t precision, uint64_t *out);

int random_get(void *buf, size_t buf_len);
WASI_MODULE int random_get(void *buf, size_t buf_len);
3 changes: 2 additions & 1 deletion src/cc/frontend/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Declaration *new_decl_asm(Expr *str) {

// Function

Function *new_func(Type *type, const Name *name, const Vector *params, int flag) {
Function *new_func(Type *type, const Name *name, const Vector *params, Table *attributes, int flag) {
assert(type->kind == TY_FUNC);
Function *func = malloc_or_die(sizeof(*func));
func->type = type;
Expand All @@ -360,6 +360,7 @@ Function *new_func(Type *type, const Name *name, const Vector *params, int flag)
func->label_table = NULL;
func->gotos = NULL;
func->extra = NULL;
func->attributes = attributes;
func->flag = flag;

return func;
Expand Down
3 changes: 2 additions & 1 deletion src/cc/frontend/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,15 @@ typedef struct Function {
Table *label_table; // <const Name*, Stmt*>
Vector *gotos; // <Stmt*>
void *extra;
Table *attributes;
int flag;
} Function;

#define FUNCF_NORETURN (1 << 0)
#define FUNCF_STACK_MODIFIED (1 << 1)
#define FUNCF_HAS_FUNCALL (1 << 2)

Function *new_func(Type *type, const Name *name, const Vector *params, int flag);
Function *new_func(Type *type, const Name *name, const Vector *params, Table *attributes, int flag);

// Declaration

Expand Down
115 changes: 76 additions & 39 deletions src/cc/frontend/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,48 +619,66 @@ static Stmt *parse_stmt(void) {
return new_stmt_expr(str_to_char_array_var(curscope, val));
}

extern inline int parse_attribute(void) {
if (consume(TK_LPAR, "`(' expected") == NULL) {
static Table *parse_attribute(Table *attributes) { // <Token*>
// __attribute__((name1, name2(p, q, ...), ...))

if (consume(TK_LPAR, "`(' expected") == NULL || consume(TK_LPAR, "`(' expected") == NULL) {
match(TK_RPAR);
match(TK_RPAR);
return 0;
return NULL;
}

int paren_count = 0;
int flag = 0;
for (bool loop = true; loop; ) {
Token *tok = match(-1);
if (tok->kind == TK_EOF) {
parse_error(PE_NOFATAL, tok, "`)' expected");
break;
}
switch (tok->kind) {
case TK_LPAR:
++paren_count;
for (;;) {
if (match(TK_RPAR))
break;
case TK_RPAR:
if (paren_count <= 0) {
loop = false;
break;
}
--paren_count;

const Token *name = consume(TK_IDENT, "attribute name expected");
if (name == NULL)
break;
case TK_IDENT:
{
static const char kNoreturn[] = "noreturn";
if (tok->end - tok->begin == sizeof(kNoreturn) - 1 &&
memcmp(tok->begin, kNoreturn, sizeof(kNoreturn) - 1) == 0)
flag |= FUNCF_NORETURN;

Vector *params = NULL;
if (match(TK_LPAR)) {
params = new_vector();
if (!match(TK_RPAR)) {
for (;;) {
Token *token = match(-1);
if (token->kind == TK_EOF) {
parse_error(PE_NOFATAL, token, "`)' expected");
break;
}
vec_push(params, token);
if (!match(TK_COMMA)) {
if (!match(TK_RPAR))
parse_error(PE_NOFATAL, token, "`)' expected");
break;
}
}
}
}
if (attributes == NULL)
attributes = alloc_table();
table_put(attributes, name->ident, params);

if (!match(TK_COMMA)) {
if (!match(TK_RPAR))
parse_error(PE_NOFATAL, NULL, "`)' expected");
break;
default: break;
}
}
return flag;

consume(TK_RPAR, "`)' expected");
return attributes;
}

static Function *define_func(Type *functype, const Token *ident, const Vector *param_vars,
int storage, int flag) {
Function *func = new_func(functype, ident->ident, functype->func.param_vars, flag);
int storage, Table *attributes) {
int flag = 0;
if (attributes != NULL) {
if (table_try_get(attributes, alloc_name("noreturn", NULL, false), NULL))
flag |= FUNCF_NORETURN;
}

Function *func = new_func(functype, ident->ident, functype->func.param_vars, attributes, flag);
func->params = param_vars;
VarInfo *varinfo = scope_find(global_scope, func->name, NULL);
if (varinfo == NULL) {
Expand All @@ -673,6 +691,18 @@ static Function *define_func(Type *functype, const Token *ident, const Vector *p
int merge_flag = (flag | predecl->defun.func->flag) & FUNCF_NORETURN;
func->flag |= merge_flag;
predecl->defun.func->flag |= merge_flag;

if (attributes != NULL) {
if (predecl->defun.func->attributes != NULL) {
const Name *name;
Vector *params;
for (int it = 0; (it = table_iterate(predecl->defun.func->attributes, it, &name, (void**)&params)) != -1; ) {
if (!table_try_get(attributes, name, NULL))
table_put(attributes, name, params);
}
}
predecl->defun.func->attributes = attributes;
}
}
}

Expand Down Expand Up @@ -706,7 +736,8 @@ static void modify_funparam_vla_type(Type *type, Scope *scope) {
}
}

static Declaration *parse_defun(Type *functype, int storage, Token *ident, const Token *tok) {
static Declaration *parse_defun(Type *functype, int storage, Token *ident, const Token *tok,
Table *attributes) {
assert(functype->kind == TY_FUNC);

const Vector *param_vars = functype->func.param_vars;
Expand All @@ -717,7 +748,7 @@ static Declaration *parse_defun(Type *functype, int storage, Token *ident, const
param_vars = new_vector();
}

Function *func = define_func(functype, ident, param_vars, storage, 0);
Function *func = define_func(functype, ident, param_vars, storage, attributes);
VarInfo *varinfo = scope_find(global_scope, ident->ident, NULL);
assert(varinfo != NULL);
if (varinfo->global.func != NULL) {
Expand Down Expand Up @@ -779,12 +810,12 @@ static Declaration *parse_defun(Type *functype, int storage, Token *ident, const
return decl;
}

static Declaration *parse_global_var_decl(Type *rawtype, int storage, Type *type, Token *ident) {
static Declaration *parse_global_var_decl(Type *rawtype, int storage, Type *type, Token *ident,
Table *attributes) {
Vector *decls = NULL;
for (;;) {
int attr = 0;
if (match(TK_ATTRIBUTE))
attr = parse_attribute();
while (match(TK_ATTRIBUTE))
attributes = parse_attribute(attributes);

if (!(type->kind == TY_PTR && type->pa.ptrof->kind == TY_FUNC) &&
type->kind != TY_VOID)
Expand Down Expand Up @@ -813,7 +844,7 @@ static Declaration *parse_global_var_decl(Type *rawtype, int storage, Type *type
parse_error(PE_NOFATAL, NULL, "ident expected");
} else {
Function *func = define_func(type, ident, type->func.param_vars, storage | VS_EXTERN,
attr);
attributes);
VarInfo *varinfo = scope_find(global_scope, ident->ident, NULL);
assert(varinfo != NULL);

Expand Down Expand Up @@ -852,6 +883,8 @@ static Declaration *parse_global_var_decl(Type *rawtype, int storage, Type *type
if (!match(TK_COMMA))
break;

attributes = NULL; // TODO: Confirm.

// Next declaration.
type = parse_declarator(rawtype, &ident);
}
Expand All @@ -868,6 +901,10 @@ static Declaration *parse_declaration(void) {
return new_decl_asm(asm_->asm_.str);
}

Table *attributes = NULL;
while (match(TK_ATTRIBUTE))
attributes = parse_attribute(attributes);

Type *rawtype = NULL;
int storage;
Token *ident;
Expand All @@ -894,12 +931,12 @@ static Declaration *parse_declaration(void) {

const Token *tok = match(TK_LBRACE);
if (tok != NULL)
return parse_defun(type, storage, ident, tok);
return parse_defun(type, storage, ident, tok, attributes);
// Function prototype declaration:
// Join with global variable declaration to handle multiple prototype declarations.
}

return parse_global_var_decl(rawtype, storage, type, ident);
return parse_global_var_decl(rawtype, storage, type, ident, attributes);
}
parse_error(PE_NOFATAL, NULL, "Unexpected token");
match(-1); // Drop the token.
Expand Down
12 changes: 10 additions & 2 deletions src/wcc/emit_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,16 @@ static void emit_import_section(EmitWasm *ew) {
error("Import: `%.*s' is not public", NAMES(name));
}

data_string(&imports_section, module_name, module_name_len); // import module name
data_string(&imports_section, name->chars, name->bytes); // import name
const char *modname = module_name;
size_t modnamelen = module_name_len;
if (info->module_name != NULL) {
modname = info->module_name->chars;
modnamelen = info->module_name->bytes;
}
const Name *fn = info->func_name;

data_string(&imports_section, modname, modnamelen); // import module name
data_string(&imports_section, fn->chars, fn->bytes); // import name
data_push(&imports_section, IMPORT_FUNC); // import kind
data_uleb128(&imports_section, -1, info->type_index); // import signature index
++imports_count;
Expand Down
27 changes: 27 additions & 0 deletions src/wcc/traverse.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static FuncInfo *register_func_info(const Name *funcname, Function *func, VarInf
info = calloc_or_die(sizeof(*info));
table_put(&func_info_table, funcname, info);
info->type_index = (uint32_t)-1;
info->func_name = funcname;

if (varinfo == NULL) {
varinfo = scope_find(global_scope, funcname, NULL);
Expand All @@ -92,6 +93,32 @@ static FuncInfo *register_func_info(const Name *funcname, Function *func, VarInf
if (info->type_index == (uint32_t)-1)
info->type_index = getsert_func_type_index(info->varinfo->type, true);
info->flag |= flag;

Table *attributes = NULL;
if (func != NULL)
attributes = func->attributes;
if (attributes == NULL && varinfo != NULL && varinfo->global.funcdecl != NULL) {
assert(varinfo->global.funcdecl->defun.func != NULL);
attributes = varinfo->global.funcdecl->defun.func->attributes;
}
if (attributes != NULL) {
const Vector *params;
if (table_try_get(attributes, alloc_name("import_module", NULL, false), (void**)&params)) {
const Token *token = params->len > 0 ? params->data[0] : NULL;
if (params->len != 1 && token->kind != TK_STR)
parse_error(PE_NOFATAL, token, "import_module: string expected");
else
info->module_name = alloc_name(token->str.buf, token->str.buf + token->str.len - 1, false);
}
if (table_try_get(attributes, alloc_name("import_name", NULL, false), (void**)&params)) {
const Token *token = params->len > 0 ? params->data[0] : NULL;
if (params->len != 1 && token->kind != TK_STR)
parse_error(PE_NOFATAL, token, "import_name: string expected");
else
info->func_name = alloc_name(token->str.buf, token->str.buf + token->str.len - 1, false);
}
}

return info;
}

Expand Down
4 changes: 1 addition & 3 deletions src/wcc/wcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

// #define USE_EMCC_AS_LINKER 1

static const char DEFAULT_IMPORT_MODULE_NAME[] = "wasi_snapshot_preview1";
static const char DEFAULT_IMPORT_MODULE_NAME[] = "env";

#define DEFAULT_STACK_SIZE (8 * 1024)

Expand Down Expand Up @@ -350,8 +350,6 @@ int main(int argc, char *argv[]) {
do_emcc_link = true;
out_type = OutObject;
}
if (import_module_name == DEFAULT_IMPORT_MODULE_NAME)
import_module_name = "env";
#endif
if (out_type >= OutExecutable && entry_point == NULL) {
entry_point = "_start";
Expand Down
2 changes: 2 additions & 0 deletions src/wcc/wcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ extern uint32_t data_end_address;
typedef struct {
Function *func;
VarInfo *varinfo;
const Name *module_name;
const Name *func_name;
const Name *bpname;
uint32_t index; // also represents symbol_index (because functions are put first in symbol table.)
int flag;
Expand Down

0 comments on commit 64d4e1e

Please sign in to comment.