diff options
Diffstat (limited to 'qbe.c')
-rw-r--r-- | qbe.c | 29 |
1 files changed, 24 insertions, 5 deletions
@@ -62,6 +62,7 @@ struct jump { JUMP_JMP, JUMP_JNZ, JUMP_RET, + JUMP_HLT, } kind; struct value *arg; struct block *blk[2]; @@ -598,6 +599,15 @@ funcret(struct func *f, struct value *v) } } +void +funchlt(struct func *f) +{ + struct block *b = f->end; + + if (!b->jump.kind) + b->jump.kind = JUMP_HLT; +} + struct gotolabel * funcgoto(struct func *f, char *name) { @@ -631,7 +641,7 @@ funclval(struct func *f, struct expr *e) case EXPRIDENT: d = e->u.ident.decl; if (d->kind != DECLOBJECT && d->kind != DECLFUNC) - error(&tok.loc, "identifier is not an object or function"); /* XXX: fix location, var name */ + error(&tok.loc, "identifier '%s' is not an object or function", d->name); if (d == f->namedecl) { fputs("data ", stdout); emitname(d->value); @@ -727,10 +737,12 @@ funcexpr(struct func *f, struct expr *e) t = arg->type; funcinst(f, IARG, qbetype(t).base, argvals[i], t->value); } - /* - if (functype->func.isnoreturn) - funcret(f, NULL); - */ + e = e->base; + if (e->kind == EXPRUNARY && e->op == TBAND) { + e = e->base; + if (e->kind == EXPRIDENT && e->u.ident.decl->u.func.isnoreturn) + funchlt(f); + } return v; case EXPRUNARY: switch (e->op) { @@ -1187,6 +1199,8 @@ static void emitjump(struct jump *j) { switch (j->kind) { + case JUMP_NONE: + break; case JUMP_RET: fputs("\tret", stdout); if (j->arg) { @@ -1209,6 +1223,11 @@ emitjump(struct jump *j) emitname(&j->blk[1]->label); putchar('\n'); break; + case JUMP_HLT: + fputs("\thlt\n", stdout); + break; + default: + assert(0); } } |