fix: repair three M7 C emission defects
emitcm7.c reimplements the emitter for sources that mention M7 syntax, and three things were lost in the port. All of them only reached M4 fixtures, because M1-M3 and M6 take the M6 fast path. Local initializers named "0". The LET/VAR case passed the declaration node to emit_lvalue, which matches only IDENT/MEMBER/INDEX and otherwise falls through to the raw expression path -- a declaration node renders there as "0", so every `var x = init;` emitted `0 = init;`. Teach emit_lvalue that a declaration names its own storage, which also fixes the catch path that had the same call. Aggregate initializers were not constant. A string-literal `const` lowered to a maker call, but C89 requires a constant expression for aggregate initializers at file scope and for automatics alike, and the build runs with -za. Restore the braced form for both the local and the global path. Slice helpers were never emitted. The final loop in m7_emit_type_helpers is commented as reusing the M3 index/slice generator but only ported the index half, so bodies called fe_slice_*/fe_full_*/fe_tail_* that no declaration defined. Emit the three slicers for array and slice types. The first defect masked the other two: wcc386 died on `0 = ...` before it could reach them, and wcl386 reports that as "Unable to invoke wcc386.exe" with no diagnostic, which is why this needed bisecting against master's output rather than reading an error message. M1-M7: 7 failed, 176 passed -> 3 failed, 180 passed. The remainder is m5 runtime, which is a separate fixture issue.
This commit is contained in:
+56
-2
@@ -294,6 +294,7 @@ static void m7_emit_drop_helpers(FeEmitter *e)
|
||||
static void m7_emit_type_helpers(FeEmitter *e)
|
||||
{
|
||||
FeType *t;
|
||||
FeType *st;
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
const char *ct;
|
||||
@@ -396,11 +397,34 @@ static void m7_emit_type_helpers(FeEmitter *e)
|
||||
if (!e->no_checks)
|
||||
fprintf(e->out,"if (i >= %lu) fe_trap_bounds(); ",t->length);
|
||||
fputs("return x.a[i]; }\n",e->out);
|
||||
if (t->slicer) {
|
||||
st=fe_type_slice(&e->check->types,t->elem);
|
||||
fprintf(e->out,"static %s %s(%s *x, unsigned long a, unsigned long b) { ",
|
||||
m7_c_type(e,st),t->slicer,m7_c_type(e,t));
|
||||
if (!e->no_checks)
|
||||
fprintf(e->out,"if (a > b || b > %lu) fe_trap_bounds(); ",t->length);
|
||||
fprintf(e->out,"return %s(x->a+a,b-a); }\n",st->maker);
|
||||
fprintf(e->out,"static %s %s(%s *x) { return %s(x,0,%lu); }\n",
|
||||
m7_c_type(e,st),t->full_slicer,m7_c_type(e,t),t->slicer,t->length);
|
||||
fprintf(e->out,"static %s %s(%s *x, unsigned long a) { return %s(x,a,%lu); }\n",
|
||||
m7_c_type(e,st),t->tail_slicer,m7_c_type(e,t),t->slicer,t->length);
|
||||
}
|
||||
} else if (t->kind==FE_TYPE_SLICE && t->indexer) {
|
||||
fprintf(e->out,"static %s %s(%s x, unsigned long i) { ",
|
||||
m7_c_type(e,t->elem),t->indexer,m7_c_type(e,t));
|
||||
if (!e->no_checks) fputs("if (i >= x.n) fe_trap_bounds(); ",e->out);
|
||||
fputs("return x.p[i]; }\n",e->out);
|
||||
if (t->slicer) {
|
||||
fprintf(e->out,"static %s %s(%s x, unsigned long a, unsigned long b) { ",
|
||||
m7_c_type(e,t),t->slicer,m7_c_type(e,t));
|
||||
if (!e->no_checks)
|
||||
fputs("if (a > b || b > x.n) fe_trap_bounds(); ",e->out);
|
||||
fprintf(e->out,"return %s(x.p+a,b-a); }\n",t->maker);
|
||||
fprintf(e->out,"static %s %s(%s x) { return %s(x,0,x.n); }\n",
|
||||
m7_c_type(e,t),t->full_slicer,m7_c_type(e,t),t->slicer);
|
||||
fprintf(e->out,"static %s %s(%s x, unsigned long a) { return %s(x,a,x.n); }\n",
|
||||
m7_c_type(e,t),t->tail_slicer,m7_c_type(e,t),t->slicer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,6 +519,14 @@ static void emit_lvalue(FeEmitter *e, FeNode *n)
|
||||
fputs(cname(n,"fe_local"),e->out);
|
||||
return;
|
||||
}
|
||||
/* A declaration names its own storage. The initializer for `let`/`var` is
|
||||
emitted as a separate assignment statement, so the declaration node is
|
||||
handed here as the target; without this it falls through to the raw
|
||||
expression path, which emits a declaration as "0" and produces `0 = ...`. */
|
||||
if (n->kind==FE_N_LET || n->kind==FE_N_VAR || n->kind==FE_N_CONST) {
|
||||
fputs(cname(n,"fe_local"),e->out);
|
||||
return;
|
||||
}
|
||||
if (n->kind==FE_N_MEMBER) {
|
||||
bt=n->a ? n->a->sem_type : 0;
|
||||
if (n->text && strcmp(n->text,".?")==0) {
|
||||
@@ -762,12 +794,31 @@ static void m7_emit_raw_expr(FeEmitter *e, FeNode *n)
|
||||
(void)x;
|
||||
}
|
||||
|
||||
/* Emit the initializer for a `const` declaration.
|
||||
|
||||
A string literal normally lowers to a maker call, but C89 requires the
|
||||
initializer of an aggregate -- at file scope and for automatics alike -- to be
|
||||
a constant expression, and the build runs with -za. Emit the slice braced
|
||||
instead. Returns non-zero when it handled the initializer. */
|
||||
static int m7_emit_const_init(FeEmitter *e, FeNode *n)
|
||||
{
|
||||
if (n->kind!=FE_N_CONST || !n->b || n->b->kind!=FE_N_LITERAL ||
|
||||
!n->b->text || n->b->text[0]!='"') return 0;
|
||||
fputs("{ (const unsigned char*)",e->out);
|
||||
emit_c_literal(e->out,n->b->text,1);
|
||||
fputs(", sizeof(",e->out);
|
||||
emit_c_literal(e->out,n->b->text,1);
|
||||
fputs(")-1 }",e->out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void emit_decl(FeEmitter *e, FeNode *n)
|
||||
{
|
||||
pad(e); fputs(m7_c_type(e,n->sem_type),e->out); fputc(' ',e->out);
|
||||
fputs(cname(n,"fe_local"),e->out);
|
||||
if (n->kind==FE_N_CONST && n->b) {
|
||||
fputs(" = ",e->out); emit_expr(e,n->b);
|
||||
fputs(" = ",e->out);
|
||||
if (!m7_emit_const_init(e,n)) emit_expr(e,n->b);
|
||||
}
|
||||
fputs(";\n",e->out);
|
||||
if ((n->kind==FE_N_LET || n->kind==FE_N_VAR) && n->sem_type &&
|
||||
@@ -1267,7 +1318,10 @@ void fe_emit_c_program(FeEmitter *e)
|
||||
if (n->kind==FE_N_GLOBAL || n->kind==FE_N_CONST) {
|
||||
fputs(m7_c_type(e,n->sem_type),e->out); fputc(' ',e->out);
|
||||
fputs(cname(n,"fe_global"),e->out);
|
||||
if (n->b) { fputs(" = ",e->out); emit_expr(e,n->b); }
|
||||
if (n->b) {
|
||||
fputs(" = ",e->out);
|
||||
if (!m7_emit_const_init(e,n)) emit_expr(e,n->b);
|
||||
}
|
||||
fputs(";\n",e->out);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user