aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--amd64/emit.c2
-rw-r--r--c/builtin.c24
-rw-r--r--c/c.c6
-rw-r--r--c/lex.c29
-rw-r--r--ir/builder.c8
-rw-r--r--ir/dump.c2
-rw-r--r--ir/ir.h3
-rw-r--r--ir/regalloc.c4
8 files changed, 65 insertions, 13 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index d61c1d3..3cae23f 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -1317,6 +1317,8 @@ emitbin(struct function *fn)
if (usebp) B(0xC9); /* leave */
B(0xC3); /* ret */
}
+ } else if (blk->jmp.t == Jtrap) {
+ DS("\x0F\x0B"); /* UD2 */
} else emitbranch(pcode, blk);
} while ((blk = blk->lnext) != fn->entry);
objdeffunc(fn->name, fn->globl, fnstart - objout.textbegin, *pcode - fnstart);
diff --git a/c/builtin.c b/c/builtin.c
index d386480..23e1872 100644
--- a/c/builtin.c
+++ b/c/builtin.c
@@ -27,9 +27,9 @@ callcheck(const struct span *span, int nparam, const union type *param, int narg
#define DEF_FNLIKE_SEMA(name, retty, ...) \
static bool \
name##_sema(struct comp *cm, struct expr *ex) { \
- static union type par[] = { __VA_ARGS__, {0} }; \
+ static union type par[] = { {{0}}, __VA_ARGS__ }; \
ex->ty = retty; \
- return callcheck(&ex->span, arraylength(par)-1, par, ex->narg, ex->sub+1); \
+ return callcheck(&ex->span, arraylength(par)-1, par+1, ex->narg, ex->sub+1); \
}
static bool
@@ -63,6 +63,15 @@ va_end_comp(struct function *fn, struct expr *ex, bool discard)
return NOREF;
}
+DEF_FNLIKE_SEMA(trap, mktype(TYVOID), )
+
+static union ref
+trap_comp(struct function *fn, struct expr *ex, bool discard)
+{
+ puttrap(fn);
+ return NOREF;
+}
+
union ref
builtin_va_arg_comp(struct function *fn, const struct expr *ex, bool discard)
{
@@ -74,6 +83,7 @@ builtin_va_arg_comp(struct function *fn, const struct expr *ex, bool discard)
#define LIST_BUILTINS(_) \
_(va_start) \
_(va_end) \
+ _(trap)
static const struct {
const char *name;
@@ -84,11 +94,11 @@ static const struct {
#undef FNS
};
-const char *intern(const char *);
void
putbuiltins(struct env *env)
{
for (int i = 0; i < arraylength(tab); ++i) {
+ const char *intern(const char *);
envadddecl(env, &(struct decl) {
.name = intern(tab[i].name),
.isbuiltin = 1,
@@ -97,5 +107,13 @@ putbuiltins(struct env *env)
}
}
+bool
+hasbuiltin(const char *name, uint len)
+{
+ for (int i = 0; i < arraylength(tab); ++i)
+ if (!strncmp(name, tab[i].name, len))
+ return 1;
+ return 0;
+}
/* vim:set ts=3 sw=3 expandtab: */
diff --git a/c/c.c b/c/c.c
index 69efed6..fc6bcc0 100644
--- a/c/c.c
+++ b/c/c.c
@@ -3438,10 +3438,12 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
useblk(fn, tr);
expreffects(fn, &sub[1]);
end = newblk(fn);
- putbranch(fn, end);
+ if (fn->curblk)
+ putbranch(fn, end);
useblk(fn, fl);
expreffects(fn, &sub[2]);
- putbranch(fn, end);
+ if (fn->curblk)
+ putbranch(fn, end);
useblk(fn, end);
return NOREF;
}
diff --git a/c/lex.c b/c/lex.c
index eab9ce3..60ce864 100644
--- a/c/lex.c
+++ b/c/lex.c
@@ -612,6 +612,7 @@ struct macro {
const struct token *tk;
int n;
} rlist;
+ void (*handlerfn)(struct lexer *, struct token *ret, struct rlist arg);
};
};
@@ -988,7 +989,7 @@ tryexpand(struct lexer *lx, struct token *tk)
if (l->macno == macidx)
return 0;
- if (mac->special) {
+ if (mac->special && !mac->fnlike) {
mac->handler(lx, tk);
pushmacstk(lx, &span, &(struct macrostack){
.rlist = { alloccopy(lx->tmparena, tk, sizeof *tk, 0), 1 },
@@ -1080,9 +1081,13 @@ expandfnmacro(struct lexer *lx, struct span *span, struct macro *mac)
joinspan(&excessspan.ex, tk.span.ex);
error(&excessspan, "macro `%s' passed %d arguments, but takes just %d", mac->name, narg, mac->nparam);
}
-
- /* make new rlist with args replaced */
- if (mac->nparam) {
+ if (mac->special) {
+ mac->handlerfn(lx, &tk, (struct rlist){argsbuf.p, argsbuf.n});
+ pushmacstk(lx, span, &(struct macrostack){
+ .rlist = { alloccopy(lx->tmparena, &tk, sizeof tk, 0), 1 },
+ .macno = mac - macros.p,
+ });
+ } else if (mac->nparam) { /* make new rlist with args replaced */
struct token lhsargforpaste;
bool lhsargpaste = 0, rhsargpaste = 0;
for (int i = 0; i < mac->rlist.n; ++i) {
@@ -1897,6 +1902,21 @@ mac__time__handler(struct lexer *lx, struct token *tk)
}
static void
+mac__has_builtin(struct lexer *lx, struct token *tk, struct rlist arg)
+{
+ extern bool hasbuiltin(const char *, uint n);
+ bool has = 0;
+ tk->t = TKNUMLIT, tk->len = 1;
+ if (arg.n == 1) {
+ if (arg.tk->t == TKIDENT)
+ has = hasbuiltin(arg.tk->s, arg.tk->len);
+ else if (in_range(arg.tk->t, TKWBEGIN_, TKWEND_))
+ has = arg.tk->len >= sizeof "__builtin_" && !memcmp(arg.tk->s, "__builtin_", 10);
+ }
+ tk->s = &"01"[has];
+}
+
+static void
addpredefmacros(void)
{
static const struct token tok_1 = { TKNUMLIT, .s = "1", .len = 1 };
@@ -1906,6 +1926,7 @@ addpredefmacros(void)
{ "__LINE__", .predefined = 1, .special = 1, .handler = mac__line__handler },
{ "__DATE__", .predefined = 1, .special = 1, .handler = mac__date__handler },
{ "__TIME__", .predefined = 1, .special = 1, .handler = mac__time__handler },
+ { "__has_builtin", .predefined = 1, .nparam = 1, .fnlike = 1, .special = 1, .handlerfn = mac__has_builtin },
{ "__STDC__", .predefined = 1, .rlist = { &tok_1, 1 } },
{ "__STDC_VERSION__", .predefined = 1, .rlist = { &tok_ver, 1 } },
{ "__STDC_HOSTED__", .predefined = 1, .rlist = { &tok_1, 1 } },
diff --git a/ir/builder.c b/ir/builder.c
index 640c1fd..1d73314 100644
--- a/ir/builder.c
+++ b/ir/builder.c
@@ -207,11 +207,19 @@ putcondbranch(struct function *fn, union ref arg, struct block *t, struct block
void
putreturn(struct function *fn, union ref r0, union ref r1)
{
+ assert(fn->curblk);
adduse(fn->curblk, USERJUMP, r0);
adduse(fn->curblk, USERJUMP, r1);
putjump(fn, Jret, r0, r1, NULL, NULL);
}
+void
+puttrap(struct function *fn)
+{
+ assert(fn->curblk);
+ putjump(fn, Jtrap, NOREF, NOREF, NULL, NULL);
+}
+
#undef putjump
/* vim:set ts=3 sw=3 expandtab: */
diff --git a/ir/dump.c b/ir/dump.c
index 2245d3f..2e54310 100644
--- a/ir/dump.c
+++ b/ir/dump.c
@@ -176,7 +176,7 @@ dumpinst(const struct instr *ins)
void
dumpblk(struct function *fn, struct block *blk)
{
- static const char *jnames[] = { 0, "b", "ret" };
+ static const char *jnames[] = { 0, "b", "ret", "trap" };
int i;
efmt(" @%d:\n", blk->id);
for (i = 0; i < blk->phi.n; ++i) {
diff --git a/ir/ir.h b/ir/ir.h
index 22b920f..f453c51 100644
--- a/ir/ir.h
+++ b/ir/ir.h
@@ -113,7 +113,7 @@ struct instr {
union ref l, r; /* args */
};
-enum jumpkind { JXXX, Jb, Jret, };
+enum jumpkind { JXXX, Jb, Jret, Jtrap, };
struct block {
int id;
@@ -263,6 +263,7 @@ void useblk(struct function *, struct block *);
void putbranch(struct function *, struct block *);
void putcondbranch(struct function *, union ref arg, struct block *t, struct block *f);
void putreturn(struct function *, union ref r0, union ref r1);
+void puttrap(struct function *);
/** fold.c **/
bool foldbinop(union ref *to, enum op, enum irclass, union ref l, union ref r);
diff --git a/ir/regalloc.c b/ir/regalloc.c
index f43bcc7..ca3ddcc 100644
--- a/ir/regalloc.c
+++ b/ir/regalloc.c
@@ -1134,10 +1134,10 @@ fini(struct rega *ra)
* b @blk
* @blk:
* NOP
- * ret
+ * ret/trap
*/
assert(p->s1 == blk);
- p->jmp.t = Jret;
+ p->jmp.t = blk->jmp.t;
p->s1 = NULL;
} else if (blk->s1) {
/* simplify: