Skip to content

Commit

Permalink
Import if required
Browse files Browse the repository at this point in the history
`__linear_memory` and `__stack_pointer`.

  * Split traversal and modification for `setjmp`
  * Skip code generation for `inline` function
  • Loading branch information
tyfkda committed Oct 20, 2024
1 parent 3541c55 commit 6668de8
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/wcc/emit_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ static void emit_import_section(EmitWasm *ew) {
uint32_t imports_count = 0;
uint32_t global_count = 0;

{
if (compile_unit_flag & CUF_LINEAR_MEMORY) {
static const char kMemoryName[] = "__linear_memory";
data_string(&imports_section, env_module_name, sizeof(env_module_name) - 1); // import module name
data_string(&imports_section, kMemoryName, sizeof(kMemoryName) - 1); // import name
Expand Down
4 changes: 4 additions & 0 deletions src/wcc/gen_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,10 @@ static void gen_defun(Function *func) {
if (func->scopes == NULL) // Prototype definition
return;

VarInfo *funcvi = scope_find(global_scope, func->name, NULL);
if (funcvi != NULL && satisfy_inline_criteria(funcvi) && !(funcvi->storage & VS_STATIC))
return;

DataStorage *code = malloc_or_die(sizeof(*code));
data_init(code);
data_open_chunk(code);
Expand Down
121 changes: 107 additions & 14 deletions src/wcc/traverse.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,11 +745,6 @@ static void traverse_defun(Function *func) {
register_func_info(func->name, func, NULL, 0);
curfunc = func;
traverse_stmt(func->body_block);
if (compile_error_count == 0) {
int count = ((FuncExtra*)func->extra)->setjmp_count;
if (count > 0)
modify_ast_for_setjmp(count);
}
curfunc = NULL;

// Static variables are traversed through global variables.
Expand Down Expand Up @@ -790,13 +785,9 @@ static void traverse_decl(Declaration *decl) {
}
}

static void add_builtins(void) {
const Name *names[2];
names[0] = alloc_name(SP_NAME, NULL, false);
int n = 1;

for (int i = 0; i < n; ++i) {
const Name *name = names[i];
static void add_builtins(int flag) {
if (flag & CUF_USE_SP) {
const Name *name = alloc_name(SP_NAME, NULL, false);
VarInfo *varinfo = scope_find(global_scope, name, NULL);
if (varinfo == NULL) {
varinfo = add_global_var(&tyVoidPtr, name);
Expand All @@ -811,7 +802,93 @@ static void add_builtins(void) {
}
}

static bool detect_compile_unit_sp(Function *func) {
if (func->flag & FUNCF_STACK_MODIFIED)
return true;
FuncExtra *extra = func->extra;
assert(extra != NULL);
if (extra->setjmp_count > 0)
return true;
FuncInfo *finfo = table_get(&func_info_table, func->name);
assert(finfo != NULL);
if (finfo->lspname != NULL)
return true;

Vector *scopes = func->scopes;
if (scopes == NULL) // Prototype definition
return false;

const Type *functype = func->type;
unsigned int param_count = functype->func.params != NULL ? functype->func.params->len : 0;
unsigned int pparam_count = 0; // Primitive parameter count

for (int i = 0; i < scopes->len; ++i) {
Scope *scope = scopes->data[i];
if (scope->vars == NULL)
continue;
for (int j = 0; j < scope->vars->len; ++j) {
VarInfo *varinfo = scope->vars->data[j];
if (!is_local_storage(varinfo)) {
// Static entity is allocated in global, not on stack.
// Extern doesn't have its entity.
// Enum members are replaced to constant value.
continue;
}

int param_index = -1;
if (i == 0 && param_count > 0) {
int k = get_funparam_index(func, varinfo->name);
if (k >= 0) {
param_index = k;
if (!is_stack_param(varinfo->type))
++pparam_count;
}
}
if ((varinfo->storage & VS_REF_TAKEN) || (is_stack_param(varinfo->type) && param_index < 0)) {
return true;
}
}
}
return pparam_count != param_count;
}

static int detect_compile_unit_memory(void) {
for (int i = 0, len = global_scope->vars->len; i < len; ++i) {
VarInfo *varinfo = global_scope->vars->data[i];
if (varinfo->storage & (VS_EXTERN | VS_ENUM_MEMBER) || varinfo->type->kind == TY_FUNC)
continue;
if (is_global_datsec_var(varinfo, global_scope))
return CUF_LINEAR_MEMORY;
}
return 0;
}

static int detect_compile_unit_flags(Vector *decls) {
int flag = detect_compile_unit_memory();

for (int i = 0, len = decls->len; i < len; ++i) {
Declaration *decl = decls->data[i];
if (decl->kind != DCL_DEFUN)
continue;

Function *func = decl->defun.func;
VarInfo *varinfo = scope_find(global_scope, func->name, NULL);
assert(varinfo != NULL);
if (satisfy_inline_criteria(varinfo) && !(varinfo->storage & VS_STATIC))
continue;

if (detect_compile_unit_sp(func)) {
flag |= CUF_USE_SP;
break;
}
}

return flag;
}

void traverse_ast(Vector *decls) {
compile_unit_flag = 0;

// Global scope
for (int k = 0; k < 2; ++k) { // 0=register, 1=traverse
for (int i = 0, len = global_scope->vars->len; i < len; ++i) {
Expand All @@ -825,13 +902,29 @@ void traverse_ast(Vector *decls) {
}
}

add_builtins();

for (int i = 0, len = decls->len; i < len; ++i) {
Declaration *decl = decls->data[i];
traverse_decl(decl);
}

compile_unit_flag = detect_compile_unit_flags(decls);

add_builtins(compile_unit_flag);

// traverse_ast_for_setjmp();
for (int i = 0, len = decls->len; i < len; ++i) {
Declaration *decl = decls->data[i];
if (decl->kind != DCL_DEFUN)
continue;
Function *func = decl->defun.func;
int count = ((FuncExtra*)func->extra)->setjmp_count;
if (count > 0) {
curfunc = func;
modify_ast_for_setjmp(count);
curfunc = NULL;
}
}

// Indirect functions.
{
const Name *name;
Expand Down
4 changes: 4 additions & 0 deletions src/wcc/wcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ enum OutType {
OutExecutable,
};

#define CUF_LINEAR_MEMORY (1 << 0)
#define CUF_USE_SP (1 << 1)

extern const char SP_NAME[];
extern const char BREAK_ADDRESS_NAME[];

Expand All @@ -135,6 +138,7 @@ extern Table gvar_info_table;
extern Table indirect_function_table; // <FuncInfo*>
extern Vector *tags; // <TagInfo*>
extern Vector *init_funcs; // <Function*>
extern int compile_unit_flag;

#define VERBOSES(str) do { if (verbose) printf("%s", str); } while (0)
#define VERBOSE(fmt, ...) do { if (verbose) printf(fmt, __VA_ARGS__); } while (0)
Expand Down
1 change: 1 addition & 0 deletions src/wcc/wcc_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Vector *functypes; // <DataStorage*>
Table indirect_function_table;
Vector *tags;
Vector *init_funcs;
int compile_unit_flag;

uint32_t get_indirect_function_index(const Name *name) {
FuncInfo *info = table_get(&indirect_function_table, name);
Expand Down

0 comments on commit 6668de8

Please sign in to comment.