diff options
| -rw-r--r-- | decl.c | 1 | ||||
| -rw-r--r-- | decl.h | 1 | ||||
| -rw-r--r-- | expr.c | 10 | ||||
| -rw-r--r-- | expr.h | 1 | ||||
| -rw-r--r-- | main.c | 1 | ||||
| -rw-r--r-- | qbe.c | 3 | ||||
| -rw-r--r-- | tests/builtin-alloca.c | 3 | ||||
| -rw-r--r-- | tests/builtin-alloca.qbe | 12 | 
8 files changed, 27 insertions, 5 deletions
| @@ -24,6 +24,7 @@ struct declaration builtinvaarg = {.kind = DECLBUILTIN};  struct declaration builtinvacopy = {.kind = DECLBUILTIN};  struct declaration builtinvaend = {.kind = DECLBUILTIN};  struct declaration builtinoffsetof = {.kind = DECLBUILTIN}; +struct declaration builtinalloca = {.kind = DECLBUILTIN};  static struct list tentativedefns = {&tentativedefns, &tentativedefns}; @@ -31,6 +31,7 @@ extern struct declaration builtinvaarg;  extern struct declaration builtinvacopy;  extern struct declaration builtinvaend;  extern struct declaration builtinoffsetof; +extern struct declaration builtinalloca;  struct declaration *mkdecl(enum declarationkind, struct type *, enum linkage);  _Bool decl(struct scope *, struct function *); @@ -443,26 +443,22 @@ postfixexpr(struct scope *s, struct expression *r)  					expect(TCOMMA, "after va_list");  					free(expect(TIDENT, "after ','"));  					// XXX: check that this was actually a parameter name? -					expect(TRPAREN, "after parameter identifier");  				} else if (r->ident.decl == &builtinvaarg) {  					e = mkexpr(EXPRBUILTIN, NULL, 0);  					e->builtin.kind = BUILTINVAARG;  					e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr);  					expect(TCOMMA, "after va_list");  					e->type = typename(s); -					expect(TRPAREN, "after typename");  				} else if (r->ident.decl == &builtinvacopy) {  					e = mkexpr(EXPRASSIGN, typevalist.base, 0);  					e->assign.l = mkunaryexpr(TMUL, exprconvert(assignexpr(s), &typevalistptr));  					expect(TCOMMA, "after target va_list");  					e->assign.r = mkunaryexpr(TMUL, exprconvert(assignexpr(s), &typevalistptr)); -					expect(TRPAREN, "after source va_list");  					e = exprconvert(e, &typevoid);  				} else if (r->ident.decl == &builtinvaend) {  					e = mkexpr(EXPRBUILTIN, &typevoid, 0);  					e->builtin.kind = BUILTINVAEND;  					exprconvert(assignexpr(s), &typevalistptr); -					expect(TRPAREN, "after va_list");  				} else if (r->ident.decl == &builtinoffsetof) {  					t = typename(s);  					expect(TCOMMA, "after type name"); @@ -474,10 +470,14 @@ postfixexpr(struct scope *s, struct expression *r)  						error(&tok.loc, "struct/union has no member named '%s'", name);  					e = mkconstexpr(&typeulong, offset);  					free(name); -					expect(TRPAREN, "after member name"); +				} else if (r->ident.decl == &builtinalloca) { +					e = mkexpr(EXPRBUILTIN, mkpointertype(&typevoid), 0); +					e->builtin.kind = BUILTINALLOCA; +					e->builtin.arg = exprconvert(assignexpr(s), &typeulong);  				} else {  					fatal("internal error; unknown builtin");  				} +				expect(TRPAREN, "after builtin parameters");  				break;  			}  			lvalueconvert(r); @@ -81,6 +81,7 @@ struct expression {  				BUILTINVASTART,  				BUILTINVAARG,  				BUILTINVAEND, +				BUILTINALLOCA,  			} kind;  			struct expression *arg;  		} builtin; @@ -59,6 +59,7 @@ main(int argc, char *argv[])  		scopeputdecl(&filescope, "__builtin_va_arg", &builtinvaarg);  		scopeputdecl(&filescope, "__builtin_va_end", &builtinvaend);  		scopeputdecl(&filescope, "__builtin_offsetof", &builtinoffsetof); +		scopeputdecl(&filescope, "__builtin_alloca", &builtinalloca);  		while (tok.kind != TEOF) {  			if (!decl(&filescope, NULL))  				error(&tok.loc, "expected declaration or function definition"); @@ -830,6 +830,9 @@ funcexpr(struct function *f, struct expression *e)  		case BUILTINVAEND:  			/* no-op */  			break; +		case BUILTINALLOCA: +			l = funcexpr(f, e->builtin.arg); +			return funcinst(f, IALLOC16, &iptr, (struct value *[]){l});  		default:  			fatal("internal error: unimplemented builtin");  		} diff --git a/tests/builtin-alloca.c b/tests/builtin-alloca.c new file mode 100644 index 0000000..f086f19 --- /dev/null +++ b/tests/builtin-alloca.c @@ -0,0 +1,3 @@ +void f(void) { +	int *x = __builtin_alloca(32); +} diff --git a/tests/builtin-alloca.qbe b/tests/builtin-alloca.qbe new file mode 100644 index 0000000..75a1fe1 --- /dev/null +++ b/tests/builtin-alloca.qbe @@ -0,0 +1,12 @@ +export +function $f() { +@start.1 +	%.1 =l alloc8 8 +@body.2 +	%.2 =l add %.1, 0 +	%.3 =l extsw 32 +	%.4 =l alloc16 %.3 +	%.5 =l copy %.4 +	storel %.5, %.2 +	ret +} | 
