mirror of https://github.com/rui314/chibicc
Add alloca()
This commit is contained in:
parent
4064871212
commit
77275c546a
|
@ -153,6 +153,7 @@ struct Obj {
|
|||
Node *body;
|
||||
Obj *locals;
|
||||
Obj *va_area;
|
||||
Obj *alloca_bottom;
|
||||
int stack_size;
|
||||
|
||||
// Static inline function
|
||||
|
|
36
codegen.c
36
codegen.c
|
@ -560,6 +560,34 @@ static void copy_struct_mem(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void builtin_alloca(void) {
|
||||
// Align size to 16 bytes.
|
||||
println(" add $15, %%rdi");
|
||||
println(" and $0xfffffff0, %%edi");
|
||||
|
||||
// Shift the temporary area by %rdi.
|
||||
println(" mov %d(%%rbp), %%rcx", current_fn->alloca_bottom->offset);
|
||||
println(" sub %%rsp, %%rcx");
|
||||
println(" mov %%rsp, %%rax");
|
||||
println(" sub %%rdi, %%rsp");
|
||||
println(" mov %%rsp, %%rdx");
|
||||
println("1:");
|
||||
println(" cmp $0, %%rcx");
|
||||
println(" je 2f");
|
||||
println(" mov (%%rax), %%r8b");
|
||||
println(" mov %%r8b, (%%rdx)");
|
||||
println(" inc %%rdx");
|
||||
println(" inc %%rax");
|
||||
println(" dec %%rcx");
|
||||
println(" jmp 1b");
|
||||
println("2:");
|
||||
|
||||
// Move alloca_bottom pointer.
|
||||
println(" mov %d(%%rbp), %%rax", current_fn->alloca_bottom->offset);
|
||||
println(" sub %%rdi, %%rax");
|
||||
println(" mov %%rax, %d(%%rbp)", current_fn->alloca_bottom->offset);
|
||||
}
|
||||
|
||||
// Generate code for a given node.
|
||||
static void gen_expr(Node *node) {
|
||||
println(" .loc %d %d", node->tok->file->file_no, node->tok->line_no);
|
||||
|
@ -732,6 +760,13 @@ static void gen_expr(Node *node) {
|
|||
return;
|
||||
}
|
||||
case ND_FUNCALL: {
|
||||
if (node->lhs->kind == ND_VAR && !strcmp(node->lhs->var->name, "alloca")) {
|
||||
gen_expr(node->args);
|
||||
println(" mov %%rax, %%rdi");
|
||||
builtin_alloca();
|
||||
return;
|
||||
}
|
||||
|
||||
int stack_args = push_args(node);
|
||||
gen_expr(node->lhs);
|
||||
|
||||
|
@ -1241,6 +1276,7 @@ static void emit_text(Obj *prog) {
|
|||
println(" push %%rbp");
|
||||
println(" mov %%rsp, %%rbp");
|
||||
println(" sub $%d, %%rsp", fn->stack_size);
|
||||
println(" mov %%rsp, %d(%%rbp)", fn->alloca_bottom->offset);
|
||||
|
||||
// Save arg registers if function is variadic
|
||||
if (fn->va_area) {
|
||||
|
|
10
parse.c
10
parse.c
|
@ -2912,8 +2912,10 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
|||
new_lvar("", pointer_to(rty));
|
||||
|
||||
fn->params = locals;
|
||||
|
||||
if (ty->is_variadic)
|
||||
fn->va_area = new_lvar("__va_area__", array_of(ty_char, 136));
|
||||
fn->alloca_bottom = new_lvar("__alloca_size__", pointer_to(ty_char));
|
||||
|
||||
tok = skip(tok, "{");
|
||||
|
||||
|
@ -2999,8 +3001,16 @@ static void scan_globals(void) {
|
|||
globals = head.next;
|
||||
}
|
||||
|
||||
static void declare_builtin_functions(void) {
|
||||
Type *ty = func_type(pointer_to(ty_void));
|
||||
ty->params = copy_type(ty_int);
|
||||
Obj *builtin = new_gvar("alloca", ty);
|
||||
builtin->is_definition = false;
|
||||
}
|
||||
|
||||
// program = (typedef | function-definition | global-variable)*
|
||||
Obj *parse(Token *tok) {
|
||||
declare_builtin_functions();
|
||||
globals = NULL;
|
||||
|
||||
while (tok->kind != TK_EOF) {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#include "test.h"
|
||||
|
||||
void *fn(int x, void *p, int y) { return p; }
|
||||
|
||||
int main() {
|
||||
int i = 0;
|
||||
|
||||
char *p1 = alloca(16);
|
||||
char *p2 = alloca(16);
|
||||
char *p3 = 1 + (char *)alloca(3) + 1;
|
||||
p3 -= 2;
|
||||
char *p4 = fn(1, alloca(16), 3);
|
||||
|
||||
ASSERT(16, p1 - p2);
|
||||
ASSERT(16, p2 - p3);
|
||||
ASSERT(16, p3 - p4);
|
||||
|
||||
memcpy(p1, "0123456789abcdef", 16);
|
||||
memcpy(p2, "ghijklmnopqrstuv", 16);
|
||||
memcpy(p3, "wxy", 3);
|
||||
|
||||
ASSERT(0, memcmp(p1, "0123456789abcdef", 16));
|
||||
ASSERT(0, memcmp(p2, "ghijklmnopqrstuv", 16));
|
||||
ASSERT(0, memcmp(p3, "wxy", 3));
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
|
@ -10,3 +10,4 @@ int memcmp(char *p, char *q, long n);
|
|||
void exit(int n);
|
||||
int vsprintf();
|
||||
long strlen(char *s);
|
||||
void *memcpy(void *dest, void *src, long n);
|
||||
|
|
Loading…
Reference in New Issue