Skip to content

Commit

Permalink
Generate relocation for longjmp
Browse files Browse the repository at this point in the history
  * Register tag in traversal stage
  • Loading branch information
tyfkda committed Feb 5, 2024
1 parent 589c3f5 commit e8fa8fe
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 27 deletions.
17 changes: 15 additions & 2 deletions src/wcc/emit_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,10 @@ void emit_tag_section(EmitWasm *ew) {
data_open_chunk(&tag_section);
data_uleb128(&tag_section, -1, tags->len); // tag count
for (int i = 0; i < tags->len; ++i) {
int typeindex = VOIDP2INT(tags->data[i]);
TagInfo *t = tags->data[i];
int attribute = 0;
data_uleb128(&tag_section, -1, attribute);
data_uleb128(&tag_section, -1, typeindex);
data_uleb128(&tag_section, -1, t->typeindex);
}
data_close_chunk(&tag_section, -1);

Expand Down Expand Up @@ -715,6 +715,19 @@ static void emit_linking_section(EmitWasm *ew) {
++count;
}
}
if (tags->len > 0) { // Tag
assert(tags->len == 1);
static const char kTagName[] = "__c_longjmp";
for (int i = 0, len = tags->len; i < len; ++i) {
// TagInfo *ti = tags->data[i];
int flags = 0;
data_push(&linking_section, SIK_SYMTAB_EVENT); // kind
data_uleb128(&linking_section, -1, flags);
data_uleb128(&linking_section, -1, i);
data_string(&linking_section, kTagName, sizeof(kTagName) - 1);
++count;
}
}
data_close_chunk(&linking_section, count);
data_close_chunk(&linking_section, -1); // Put payload size.

Expand Down
48 changes: 34 additions & 14 deletions src/wcc/gen_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1746,21 +1746,13 @@ void gen(Vector *decls) {

////////////////////////////////////////////////

static int register_longjmp_tag(void) {
// Exception type: (void*, int)
Vector *params = new_vector();
vec_push(params, &tyInt);
vec_push(params, &tyVoidPtr);
Type *functype = new_func_type(&tyVoid, params, false);
int typeindex = getsert_func_type_index(functype, true);
return getsert_tag(typeindex);
}

static void gen_builtin_setjmp(Expr *expr, enum BuiltinFunctionPhase phase) {
if (phase == BFP_TRAVERSE) {
FuncExtra *extra = curfunc->extra;
assert(extra != NULL);
++extra->setjmp_count;

register_longjmp_tag();
return;
}

Expand All @@ -1770,6 +1762,8 @@ static void gen_builtin_setjmp(Expr *expr, enum BuiltinFunctionPhase phase) {
}

static void gen_builtin_longjmp(Expr *expr, enum BuiltinFunctionPhase phase) {
if (phase == BFP_TRAVERSE)
register_longjmp_tag();
if (phase != BFP_GEN)
return;

Expand All @@ -1793,9 +1787,22 @@ static void gen_builtin_longjmp(Expr *expr, enum BuiltinFunctionPhase phase) {
}

gen_expr(args->data[0], true);
int tag = register_longjmp_tag();
TagInfo *ti = register_longjmp_tag();
ADD_CODE(OP_THROW);
ADD_ULEB128(tag);
if (out_type >= OutExecutable) {
ADD_ULEB128(ti->index);
} else {
FuncExtra *extra = curfunc->extra;
DataStorage *code = extra->code;
RelocInfo *ri = calloc_or_die(sizeof(*ri));
ri->type = R_WASM_TAG_INDEX_LEB;
ri->offset = code->len;
ri->addend = 0;
ri->index = ti->symbol_index;
vec_push(extra->reloc_code, ri);

ADD_VARUINT32(ti->index);
}
}

static void gen_builtin_try_catch_longjmp(Expr *expr, enum BuiltinFunctionPhase phase) {
Expand All @@ -1815,8 +1822,21 @@ static void gen_builtin_try_catch_longjmp(Expr *expr, enum BuiltinFunctionPhase
gen_stmt(try_block_expr->block, false);
ADD_CODE(OP_BR, 2);
} ADD_CODE(OP_CATCH); {
int tag = register_longjmp_tag();
ADD_ULEB128(tag);
TagInfo *ti = register_longjmp_tag();
if (out_type >= OutExecutable) {
ADD_ULEB128(ti->index);
} else {
FuncExtra *extra = curfunc->extra;
DataStorage *code = extra->code;
RelocInfo *ri = calloc_or_die(sizeof(*ri));
ri->type = R_WASM_TAG_INDEX_LEB;
ri->offset = code->len;
ri->addend = 0;
ri->index = ti->symbol_index;
vec_push(extra->reloc_code, ri);

ADD_VARUINT32(ti->index);
}

// Assume env has no side effect.
Expr *env = args->data[0];
Expand Down
6 changes: 6 additions & 0 deletions src/wcc/traverse.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,12 @@ uint32_t traverse_ast(Vector *decls, Vector *exports, uint32_t stack_size) {
info->non_prim.symbol_index = symbol_index++;
}
}

// Tag
for (int i = 0, len = tags->len; i < len; ++i) {
TagInfo *ti = tags->data[i];
ti->symbol_index = symbol_index++;
}
}

{
Expand Down
2 changes: 1 addition & 1 deletion src/wcc/wasm_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ enum RelocType {
R_WASM_GLOBAL_INDEX_LEB = 7,
R_WASM_FUNCTION_OFFSET_I32 = 8,
R_WASM_SECTION_OFFSET_I32 = 9,
R_WASM_EVENT_INDEX_LEB = 10,
R_WASM_TAG_INDEX_LEB = 10, // R_WASM_EVENT_INDEX_LEB
R_WASM_GLOBAL_INDEX_I32 = 13,
R_WASM_MEMORY_ADDR_LEB64 = 14,
R_WASM_MEMORY_ADDR_SLEB64 = 15,
Expand Down
11 changes: 9 additions & 2 deletions src/wcc/wcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ typedef struct {
};
} GVarInfo;

typedef struct {
int typeindex;
uint32_t index;
uint32_t symbol_index;
} TagInfo;

// traverse
uint32_t traverse_ast(Vector *decls, Vector *exports, uint32_t stack_size);

Expand Down Expand Up @@ -125,7 +131,7 @@ enum OutType out_type;
extern Table func_info_table;
extern Table gvar_info_table;
extern Table indirect_function_table;
extern Vector *tags; // <int>
extern Vector *tags; // <TagInfo*>

#define VERBOSES(str) do { if (verbose) printf("%s", str); } while (0)
#define VERBOSE(fmt, ...) do { if (verbose) printf(fmt, __VA_ARGS__); } while (0)
Expand All @@ -134,7 +140,8 @@ uint32_t get_indirect_function_index(const Name *name);
GVarInfo *register_gvar_info(const Name *name, VarInfo *varinfo);
GVarInfo *get_gvar_info_from_name(const Name *name);
int getsert_func_type(unsigned char *buf, size_t size, bool reg);
int getsert_tag(int typeindex);
TagInfo *getsert_tag(int typeindex);
TagInfo *register_longjmp_tag(void);

void write_wasm_header(FILE *ofp);

Expand Down
30 changes: 22 additions & 8 deletions src/wcc/wcc_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,29 @@ int getsert_func_type(unsigned char *buf, size_t size, bool reg) {
return -1;
}

int getsert_tag(int typeindex) {
int len = tags->len;
for (int i = 0; i < len; ++i) {
int t = VOIDP2INT(tags->data[i]);
if (t == typeindex)
return i;
TagInfo *getsert_tag(int typeindex) {
uint32_t len = tags->len;
for (uint32_t i = 0; i < len; ++i) {
TagInfo *t = tags->data[i];
if (t->typeindex == typeindex)
return t;
}
vec_push(tags, INT2VOIDP(typeindex));
return len;

TagInfo *t = calloc_or_die(sizeof(*t));
t->typeindex = typeindex;
t->index = len;
vec_push(tags, t);
return t;
}

TagInfo *register_longjmp_tag(void) {
// Exception type: (void*, int)
Vector *params = new_vector();
vec_push(params, &tyInt);
vec_push(params, &tyVoidPtr);
Type *functype = new_func_type(&tyVoid, params, false);
int typeindex = getsert_func_type_index(functype, true);
return getsert_tag(typeindex);
}

//
Expand Down

0 comments on commit e8fa8fe

Please sign in to comment.