fix: emit mem.create and mem.alloc_slice on the M7 path
m7_emit_call reimplements call emission and only carried over mem.destroy and
mem.replace, so every mem.create/mem.alloc_slice fell through to the generic
member path and emitted `fe_missing.create(0)`. wcc386 does not diagnose that
-- it terminates with exit 255, which wcl386 reports as "Unable to invoke
wcc386.exe" with no message at all.
The breakage covered all 17 allocation sites in m5/runtime.fe, and it was
invisible because m5-owned and m5-defer only emit C; m5-runtime is the one M5
fixture that compiles and links what was generated.
Also make runtime.fe legal: `run` used `try` while returning i32, which SPEC
allows only in a function returning an error union. It is `-> !i32` now, which
M7 accepts because contextual success construction lands with it, and
runtime.c takes the { error, value } struct the error union lowers to.
Found by calling wcc386 directly instead of through wcl386, which is the only
way to see a compiler crash here.
M1-M7: 183 passed.
This commit is contained in:
@@ -595,6 +595,28 @@ static void m7_emit_call(FeEmitter *e, FeNode *n)
|
|||||||
emit_expr(e,n->children->next); fputc(')',e->out);
|
emit_expr(e,n->children->next); fputc(')',e->out);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (n->a && n->a->kind==FE_N_MEMBER && n->a->a &&
|
||||||
|
n->a->a->kind==FE_N_IDENT && n->a->a->text &&
|
||||||
|
strcmp(n->a->a->text,"mem")==0 && n->a->b && n->a->b->text &&
|
||||||
|
strcmp(n->a->b->text,"create")==0 && n->children) {
|
||||||
|
FeType *created=n->children->sem_type;
|
||||||
|
FeType *owned=fe_type_owned(&e->check->types,created);
|
||||||
|
FeType *result=fe_type_error_union(&e->check->types,owned);
|
||||||
|
fputs(result->alloc_cname ? result->alloc_cname : "fe_bad_alloc",e->out);
|
||||||
|
fputc('(',e->out); emit_expr(e,n->children); fputc(')',e->out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (n->a && n->a->kind==FE_N_MEMBER && n->a->a &&
|
||||||
|
n->a->a->kind==FE_N_IDENT && n->a->a->text &&
|
||||||
|
strcmp(n->a->a->text,"mem")==0 && n->a->b && n->a->b->text &&
|
||||||
|
strcmp(n->a->b->text,"alloc_slice")==0 && n->children &&
|
||||||
|
n->children->next) {
|
||||||
|
FeType *result=n->sem_type;
|
||||||
|
fputs(result && result->alloc_cname ? result->alloc_cname :
|
||||||
|
"fe_bad_slice_alloc",e->out);
|
||||||
|
fputc('(',e->out); emit_expr(e,n->children->next); fputc(')',e->out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (n->text && (strcmp(n->text,"@print")==0 ||
|
if (n->text && (strcmp(n->text,"@print")==0 ||
|
||||||
strcmp(n->text,"@fprint")==0 || strcmp(n->text,"@sprint")==0)) {
|
strcmp(n->text,"@fprint")==0 || strcmp(n->text,"@sprint")==0)) {
|
||||||
emit_m4_builtin(e,n);
|
emit_m4_builtin(e,n);
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
extern void *malloc(size_t size);
|
extern void *malloc(size_t size);
|
||||||
extern void free(void *p);
|
extern void free(void *p);
|
||||||
|
|
||||||
extern long fe_m5_runtime_run(long mode);
|
/* `run` returns !i32, which lowers to { error, value }. */
|
||||||
|
struct fe_result_value_9 { unsigned short e; long v; };
|
||||||
|
extern struct fe_result_value_9 fe_m5_runtime_run(long mode);
|
||||||
extern unsigned short fe_m5_runtime_conditional(unsigned char flag);
|
extern unsigned short fe_m5_runtime_conditional(unsigned char flag);
|
||||||
extern unsigned short fe_m5_runtime_argument_cleanup(void);
|
extern unsigned short fe_m5_runtime_argument_cleanup(void);
|
||||||
extern unsigned short fe_m5_runtime_owned_slice(unsigned long n);
|
extern unsigned short fe_m5_runtime_owned_slice(unsigned long n);
|
||||||
@@ -64,9 +66,10 @@ void m5_free(void *p)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
if (fe_m5_runtime_run(0) != 0) return 1;
|
struct fe_result_value_9 r;
|
||||||
if (fe_m5_runtime_run(1) != 9) return 2;
|
r = fe_m5_runtime_run(0); if (r.e != 0 || r.v != 0) return 1;
|
||||||
if (fe_m5_runtime_run(2) != 0) return 3;
|
r = fe_m5_runtime_run(1); if (r.e != 0 || r.v != 9) return 2;
|
||||||
|
r = fe_m5_runtime_run(2); if (r.e != 0 || r.v != 0) return 3;
|
||||||
if (fe_m5_runtime_conditional(0) != 0) return 4;
|
if (fe_m5_runtime_conditional(0) != 0) return 4;
|
||||||
if (fe_m5_runtime_conditional(1) != 0) return 5;
|
if (fe_m5_runtime_conditional(1) != 0) return 5;
|
||||||
if (fe_m5_runtime_argument_cleanup() != 0) return 6;
|
if (fe_m5_runtime_argument_cleanup() != 0) return 6;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ unit m5_runtime;
|
|||||||
|
|
||||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||||
|
|
||||||
pub fn run(mode: i32) -> i32 {
|
pub fn run(mode: i32) -> !i32 {
|
||||||
var p: ^i32 = try mem.create(0);
|
var p: ^i32 = try mem.create(0);
|
||||||
defer { mem.destroy(p); }
|
defer { mem.destroy(p); }
|
||||||
p.^ = 7;
|
p.^ = 7;
|
||||||
|
|||||||
Reference in New Issue
Block a user