aboutsummaryrefslogtreecommitdiff
path: root/qbe.c
diff options
context:
space:
mode:
Diffstat (limited to 'qbe.c')
-rw-r--r--qbe.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/qbe.c b/qbe.c
index a6781dd..5c76bb2 100644
--- a/qbe.c
+++ b/qbe.c
@@ -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);
}
}