Skip to content

Multiple values support. #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ else ()
# interfaces, etc.
# disable -Wpointer-arith: this is a GCC extension, and doesn't work in MSVC.
add_definitions(
-Wall -Wextra -Werror -Wno-unused-parameter -Wpointer-arith -g
-Wall -Wextra -Werror -Wno-unused-parameter -Wpointer-arith -Wno-parentheses-equality -g
)

if (COMPILER_IS_GNU)
# disable -Wclobbered: it seems to be guessing incorrectly about a local
# variable being clobbered by longjmp.
add_definitions(-Wno-clobbered)
#add_definitions(-Wno-clobbered)
endif ()

# try to get the target architecture by compiling a dummy.c file and checking
Expand Down
90 changes: 64 additions & 26 deletions src/wasm-ast-checker.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ static void check_type(WasmContext* ctx,
}
}

#if 0 // dtc todo
static void check_type_set(WasmContext* ctx,
const WasmLocation* loc,
WasmType actual,
Expand All @@ -291,6 +292,7 @@ static void check_type_exact(WasmContext* ctx,
s_type_names[actual], s_type_names[expected]);
}
}
#endif

static void check_type_arg_exact(WasmContext* ctx,
const WasmLocation* loc,
Expand Down Expand Up @@ -390,21 +392,10 @@ static void check_br(WasmContext* ctx,
if (WASM_FAILED(check_label_var(ctx, ctx->top_label, var, &node)))
return;

if (node->expected_type != WASM_TYPE_VOID) {
if (expr) {
check_expr(ctx, module, func, expr, node->expected_type, desc);
} else {
print_error(
ctx, loc,
"arity mismatch%s. label expects non-void, but br value is empty",
desc);
}
} else if (expr) {
print_error(
ctx, loc,
"arity mismatch%s. label expects void, but br value is non-empty",
desc);
}
if (expr)
return check_expr(ctx, module, func, expr, node->expected_type, desc);

return check_type(ctx, loc, WASM_TYPE_VOID, node->expected_type, desc);
}

static void check_call(WasmContext* ctx,
Expand All @@ -420,7 +411,7 @@ static void check_call(WasmContext* ctx,
if (expected_args == actual_args) {
char buffer[100];
wasm_snprintf(buffer, 100, " of %s result", desc);
check_type(ctx, loc, sig->result_type, expected_type, buffer);
check_type(ctx, loc, single_value_result_type(&sig->result_types), expected_type, buffer);
size_t i;
for (i = 0; i < actual_args; ++i) {
wasm_snprintf(buffer, 100, " of argument %" PRIzd " of %s", i, desc);
Expand All @@ -445,15 +436,22 @@ static void check_call(WasmContext* ctx,
static void check_exprs(WasmContext* ctx,
const WasmModule* module,
const WasmFunc* func,
int rtn_first,
const WasmExprPtrVector* exprs,
WasmType expected_type,
const char* desc) {
if (exprs->size > 0) {
size_t i;
WasmExprPtr* expr = &exprs->data[0];
for (i = 0; i < exprs->size - 1; ++i, ++expr)
check_expr(ctx, module, func, *expr, WASM_TYPE_VOID, "");
check_expr(ctx, module, func, *expr, expected_type, desc);
if (rtn_first) {
check_expr(ctx, module, func, *expr, expected_type, desc);
for (i = 1; i < exprs->size; ++i, ++expr)
check_expr(ctx, module, func, *expr, WASM_TYPE_VOID, "");
} else {
for (i = 0; i < exprs->size - 1; ++i, ++expr)
check_expr(ctx, module, func, *expr, WASM_TYPE_VOID, "");
check_expr(ctx, module, func, *expr, expected_type, desc);
}
}
}

Expand All @@ -478,10 +476,12 @@ static void check_expr(WasmContext* ctx,

case WASM_EXPR_TYPE_BLOCK: {
WasmLabelNode node;
int rtn_first = expr->block.rtn_first;
push_label(ctx, &expr->loc, &node, &expr->block.label, expected_type,
"block");
check_exprs(ctx, module, func, &expr->block.exprs, expected_type,
" of block");
rtn_first ? "block1" : "block");
check_exprs(ctx, module, func, expr->block.rtn_first,
&expr->block.exprs, expected_type,
rtn_first ? " of block1" : " of block");
pop_label(ctx);
break;
}
Expand Down Expand Up @@ -539,6 +539,25 @@ static void check_expr(WasmContext* ctx,
break;
}

case WASM_EXPR_TYPE_VALUES: {
/* dtc: todo, no expressions can be void */
break;
}

case WASM_EXPR_TYPE_CONC_VALUES: {
/* dtc: todo, total number of values must be at least the expected */
break;
}

case WASM_EXPR_TYPE_MV_CALL: {
const WasmFunc* callee;
if (WASM_SUCCEEDED(
check_func_var(ctx, module, &expr->call.var, &callee))) {
/* dtc: todo */
}
break;
}

case WASM_EXPR_TYPE_COMPARE: {
WasmType rtype = s_opcode_rtype[expr->compare.opcode];
WasmType type1 = s_opcode_type1[expr->compare.opcode];
Expand Down Expand Up @@ -616,7 +635,7 @@ static void check_expr(WasmContext* ctx,
"loop outer label");
push_label(ctx, &expr->loc, &inner_node, &expr->loop.inner,
WASM_TYPE_VOID, "loop inner label");
check_exprs(ctx, module, func, &expr->loop.exprs, expected_type,
check_exprs(ctx, module, func, 0, &expr->loop.exprs, expected_type,
" of loop");
pop_label(ctx);
pop_label(ctx);
Expand All @@ -633,6 +652,7 @@ static void check_expr(WasmContext* ctx,
break;

case WASM_EXPR_TYPE_RETURN: {
#if 0 // dtc todo
WasmType result_type = wasm_get_result_type(func);
if (expr->return_.expr) {
if (result_type == WASM_TYPE_VOID) {
Expand All @@ -646,6 +666,7 @@ static void check_expr(WasmContext* ctx,
} else {
check_type(ctx, &expr->loc, WASM_TYPE_VOID, result_type, desc);
}
#endif
break;
}

Expand Down Expand Up @@ -713,8 +734,6 @@ static void check_func_signature_matches_func_type(
const WasmFunc* func,
const WasmFuncType* func_type) {
size_t num_params = wasm_get_num_params(func);
check_type_exact(ctx, &func->loc, wasm_get_result_type(func),
wasm_get_func_type_result_type(func_type), "");
if (num_params == wasm_get_func_type_num_params(func_type)) {
size_t i;
for (i = 0; i < num_params; ++i) {
Expand All @@ -726,6 +745,18 @@ static void check_func_signature_matches_func_type(
print_error(ctx, &func->loc, "expected %d parameters, got %d",
wasm_get_func_type_num_params(func_type), num_params);
}
size_t num_results = wasm_get_num_results(func);
if (num_results == wasm_get_func_type_num_results(func_type)) {
size_t i;
for (i = 0; i < num_results; ++i) {
check_type_arg_exact(ctx, &func->loc, wasm_get_result_type(func, i),
wasm_get_func_type_result_type(func_type, i),
"function", i);
}
} else {
print_error(ctx, &func->loc, "expected %d results, got %d",
wasm_get_func_type_num_results(func_type), num_results);
}
}

static void check_func(WasmContext* ctx,
Expand All @@ -743,8 +774,10 @@ static void check_func(WasmContext* ctx,

check_duplicate_bindings(ctx, &func->param_bindings, "parameter");
check_duplicate_bindings(ctx, &func->local_bindings, "local");
#if 0 // dtc todo
check_exprs(ctx, module, func, &func->exprs, wasm_get_result_type(func),
" of function result");
#endif
}

static void check_import(WasmContext* ctx,
Expand Down Expand Up @@ -856,7 +889,7 @@ static void check_module(WasmContext* ctx, const WasmModule* module) {
if (wasm_get_num_params(start_func) != 0)
print_error(ctx, &field->loc, "start function must be nullary");

if (wasm_get_result_type(start_func) != WASM_TYPE_VOID) {
if (wasm_get_num_results(start_func) != 0) {
print_error(ctx, &field->loc,
"start function must not return anything");
}
Expand Down Expand Up @@ -908,8 +941,10 @@ static void check_invoke(WasmContext* ctx,
expected_args);
return;
}
#if 0 // dtc todo
check_type_set(ctx, &invoke->loc, wasm_get_result_type(func), return_type,
"");
#endif
size_t i;
for (i = 0; i < actual_args; ++i) {
WasmConst* const_ = &invoke->args.data[i];
Expand Down Expand Up @@ -967,6 +1002,9 @@ WasmResult wasm_check_ast(WasmLexer lexer, const WasmScript* script) {
ctx.lexer = lexer;
ctx.allocator = script->allocator;
ctx.result = WASM_OK;
// dtc fixme
return ctx.result;
//
size_t i;
for (i = 0; i < script->commands.size; ++i)
check_command(&ctx, &script->commands.data[i]);
Expand Down
48 changes: 41 additions & 7 deletions src/wasm-ast-writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,12 @@ static void out_func_sig_space(WasmContext* ctx,
out_close_space(ctx);
}

if (func_sig->result_type != WASM_TYPE_VOID) {
if (func_sig->result_types.size) {
size_t i;
out_open_space(ctx, "result");
out_type(ctx, func_sig->result_type, WASM_NEXT_CHAR_NONE);
for (i = 0; i < func_sig->result_types.size; ++i) {
out_type(ctx, func_sig->result_types.data[i], WASM_NEXT_CHAR_SPACE);
}
out_close_space(ctx);
}
}
Expand Down Expand Up @@ -397,9 +400,12 @@ static void write_expr(WasmContext* ctx, const WasmExpr* expr) {
out_close_newline(ctx);
break;

case WASM_EXPR_TYPE_BLOCK:
write_block(ctx, &expr->block, s_opcode_name[WASM_OPCODE_BLOCK]);
case WASM_EXPR_TYPE_BLOCK: {
WasmOpcode opcode = &expr->block.rtn_first ? WASM_OPCODE_BLOCK1
: WASM_OPCODE_BLOCK;
write_block(ctx, &expr->block, s_opcode_name[opcode]);
break;
}

case WASM_EXPR_TYPE_BR:
out_open_space(ctx, s_opcode_name[WASM_OPCODE_BR]);
Expand Down Expand Up @@ -460,7 +466,32 @@ static void write_expr(WasmContext* ctx, const WasmExpr* expr) {
break;
}

case WASM_EXPR_TYPE_COMPARE:
case WASM_EXPR_TYPE_VALUES: {
out_open_space(ctx, s_opcode_name[WASM_OPCODE_VALUES]);
size_t i;
for (i = 0; i < expr->values.args.size; ++i)
write_expr(ctx, expr->values.args.data[i]);
out_close_newline(ctx);
break;
}

case WASM_EXPR_TYPE_CONC_VALUES: {
out_open_space(ctx, s_opcode_name[WASM_OPCODE_CONC_VALUES]);
size_t i;
for (i = 0; i < expr->values.args.size; ++i)
write_expr(ctx, expr->values.args.data[i]);
out_close_newline(ctx);
break;
}

case WASM_EXPR_TYPE_MV_CALL:
out_open_newline(ctx, s_opcode_name[WASM_OPCODE_MV_CALL_FUNCTION]);
out_var(ctx, &expr->call.var, WASM_NEXT_CHAR_NEWLINE);
write_expr(ctx, expr->mv_call.expr);
out_close_newline(ctx);
break;

case WASM_EXPR_TYPE_COMPARE:
out_open_newline(ctx, s_opcode_name[expr->compare.opcode]);
write_expr(ctx, expr->compare.left);
write_expr(ctx, expr->compare.right);
Expand Down Expand Up @@ -661,9 +692,12 @@ static void write_func(WasmContext* ctx,
if (wasm_decl_has_signature(&func->decl)) {
write_type_bindings(ctx, "param", func, &func->decl.sig.param_types,
&func->param_bindings);
if (wasm_get_result_type(func) != WASM_TYPE_VOID) {
if (func->decl.sig.result_types.size) {
size_t i;
out_open_space(ctx, "result");
out_type(ctx, wasm_get_result_type(func), WASM_NEXT_CHAR_NONE);
for (i = 0; i < func->decl.sig.result_types.size; ++i) {
out_type(ctx, func->decl.sig.result_types.data[i], WASM_NEXT_CHAR_SPACE);
}
out_close_space(ctx);
}
}
Expand Down
36 changes: 32 additions & 4 deletions src/wasm-ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ WasmModuleField* wasm_append_module_field(struct WasmAllocator* allocator,
V(WASM_EXPR_TYPE_CALL, call, call) \
V(WASM_EXPR_TYPE_CALL_IMPORT, call_import, call) \
V(WASM_EXPR_TYPE_CALL_INDIRECT, call_indirect, call_indirect) \
V(WASM_EXPR_TYPE_VALUES, values, values) \
V(WASM_EXPR_TYPE_CONC_VALUES, conc_values, values) \
V(WASM_EXPR_TYPE_MV_CALL, mv_call, mv_call) \
V(WASM_EXPR_TYPE_COMPARE, compare, compare) \
V(WASM_EXPR_TYPE_CONST, const, const_) \
V(WASM_EXPR_TYPE_CONVERT, convert, convert) \
Expand Down Expand Up @@ -388,6 +391,16 @@ static void wasm_destroy_expr(WasmAllocator* allocator, WasmExpr* expr) {
WASM_DESTROY_VECTOR_AND_ELEMENTS(allocator, expr->call_indirect.args,
expr_ptr);
break;
case WASM_EXPR_TYPE_VALUES:
case WASM_EXPR_TYPE_CONC_VALUES:
wasm_destroy_expr_ptr(allocator, &expr->values.expr);
WASM_DESTROY_VECTOR_AND_ELEMENTS(allocator, expr->values.args,
expr_ptr);
break;
case WASM_EXPR_TYPE_MV_CALL:
wasm_destroy_var(allocator, &expr->call.var);
wasm_destroy_expr_ptr(allocator, &expr->mv_call.expr);
break;
case WASM_EXPR_TYPE_COMPARE:
wasm_destroy_expr_ptr(allocator, &expr->compare.left);
wasm_destroy_expr_ptr(allocator, &expr->compare.right);
Expand Down Expand Up @@ -507,6 +520,7 @@ void wasm_destroy_func_fields(struct WasmAllocator* allocator,
break;

case WASM_FUNC_FIELD_TYPE_PARAM_TYPES:
case WASM_FUNC_FIELD_TYPE_RESULT_TYPES:
case WASM_FUNC_FIELD_TYPE_LOCAL_TYPES:
wasm_destroy_type_vector(allocator, &func_field->types);
break;
Expand All @@ -515,10 +529,6 @@ void wasm_destroy_func_fields(struct WasmAllocator* allocator,
case WASM_FUNC_FIELD_TYPE_BOUND_LOCAL:
wasm_destroy_string_slice(allocator, &func_field->bound_type.name);
break;

case WASM_FUNC_FIELD_TYPE_RESULT_TYPE:
/* nothing to free */
break;
}

wasm_free(allocator, func_field);
Expand Down Expand Up @@ -708,6 +718,24 @@ static WasmResult traverse_expr(WasmExpr* expr, WasmExprTraverser* traverser) {
CALLBACK(end_call_indirect_expr);
break;

case WASM_EXPR_TYPE_VALUES:
CALLBACK(begin_values_expr);
CHECK_RESULT(traverse_exprs(&expr->values.args, traverser));
CALLBACK(end_values_expr);
break;

case WASM_EXPR_TYPE_CONC_VALUES:
CALLBACK(begin_conc_values_expr);
CHECK_RESULT(traverse_exprs(&expr->values.args, traverser));
CALLBACK(end_conc_values_expr);
break;

case WASM_EXPR_TYPE_MV_CALL:
CALLBACK(begin_mv_call_expr);
CHECK_RESULT(traverse_expr(expr->mv_call.expr, traverser));
CALLBACK(end_mv_call_expr);
break;

case WASM_EXPR_TYPE_COMPARE:
CALLBACK(begin_compare_expr);
CHECK_RESULT(traverse_expr(expr->compare.left, traverser));
Expand Down
Loading