diff options
| -rw-r--r-- | amd64/emit.c | 2 | ||||
| -rw-r--r-- | c/builtin.c | 24 | ||||
| -rw-r--r-- | c/c.c | 6 | ||||
| -rw-r--r-- | c/lex.c | 29 | ||||
| -rw-r--r-- | ir/builder.c | 8 | ||||
| -rw-r--r-- | ir/dump.c | 2 | ||||
| -rw-r--r-- | ir/ir.h | 3 | ||||
| -rw-r--r-- | ir/regalloc.c | 4 |
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: */ @@ -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; } @@ -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: */ @@ -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) { @@ -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: |