Skip to content

Commit

Permalink
impl va_list
Browse files Browse the repository at this point in the history
  • Loading branch information
omdxp committed Sep 9, 2024
1 parent 65a3ca2 commit e765795
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 16 deletions.
4 changes: 1 addition & 3 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1076,9 +1076,7 @@ struct _x86_generator_private *x86_generator_private(struct generator *gen) {

void codegen_generate_expression(struct generator *generator, struct node *node,
int flags) {
codegen_generate_expressionable(
node, history_down(x86_generator_private(generator)->remembered.history,
flags));
codegen_generate_expressionable(node, history_begin(flags));
}

void codegen_end_expression(struct generator *generator) {}
Expand Down
113 changes: 102 additions & 11 deletions preprocessor/static_includes/stdarg.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,110 @@
#include "compiler.h"
#include "helpers/vector.h"

void native_test_function(struct generator *generator,
struct native_function *func, struct vector *args) {
generator->asm_push("; test");
struct datatype dtype;
dtype.type = DATA_TYPE_INT;
dtype.size = sizeof(int);
generator->ret(&dtype, "42");
// va_start(va_list, last_arg)
void native_va_start(struct generator *generator, struct native_function *func,
struct vector *args) {
struct compile_process *compiler = generator->compiler;
if (vector_count(args) != 2) {
compiler_error(compiler, "va_start expects 2 arguments, %d given",
vector_count(args));
}

struct node *list_arg = vector_peek_ptr(args);
struct node *stack_arg = vector_peek_ptr(args);
if (stack_arg->type != NODE_TYPE_IDENTIFIER) {
compiler_error(compiler,
"va_start expects an identifier as the second argument");
}

generator->asm_push("; va_start on %s", stack_arg->sval);
vector_set_peek_pointer(args, 0);
generator->generate_expression(generator, stack_arg, EXPRESSION_GET_ADDRESS);

struct resolver_result *result =
resolver_follow(compiler->resolver, list_arg);
assert(resolver_result_ok(result));

struct resolver_entity *list_arg_entity = resolver_result_entity_root(result);
struct generator_entity_address address_out;
generator->entity_address(generator, list_arg_entity, &address_out);
generator->asm_push("mov dword [%s], ebx", address_out.address);
generator->asm_push("; va_start end for %s", stack_arg->sval);

struct datatype void_datatype;
datatype_set_void(&void_datatype);
generator->ret(&void_datatype, "0");
}

// va_arg(va_list, type)
void native_builtin_va_arg(struct generator *generator,
struct native_function *func, struct vector *args) {
struct compile_process *compiler = generator->compiler;
if (vector_count(args) != 2) {
compiler_error(compiler, "va_arg expects 2 arguments, %d given",
vector_count(args));
}

generator->asm_push("; native __builtin_va_arg start");
vector_set_peek_pointer(args, 0);
struct node *list_arg = vector_peek_ptr(args);
generator->generate_expression(generator, list_arg, EXPRESSION_GET_ADDRESS);

struct node *size_arg = vector_peek_ptr(args);
if (size_arg->type != NODE_TYPE_NUMBER) {
compiler_error(compiler, "va_arg expects a number as the second argument");
}

generator->asm_push("add dword [ebx], %d", size_arg->llnum);
generator->asm_push("mov dword eax, [ebx]");
struct datatype void_dtype;
datatype_set_void(&void_dtype);
void_dtype.pointer_depth++;
void_dtype.flags |= DATATYPE_FLAG_IS_POINTER;
generator->ret(&void_dtype, "dword [eax]");
generator->asm_push("; native __builtin_va_arg end");
}

// va_end(va_list)
void native_va_end(struct generator *generator, struct native_function *func,
struct vector *args) {
struct compile_process *compiler = generator->compiler;
if (vector_count(args) != 1) {
compiler_error(compiler, "va_end expects 1 argument, %d given",
vector_count(args));
}

struct node *list_arg = vector_peek_ptr(args);
if (list_arg->type != NODE_TYPE_IDENTIFIER) {
compiler_error(compiler, "va_end expects an identifier as the argument");
}

generator->asm_push("; va_end start for %s", list_arg->sval);
vector_set_peek_pointer(args, 0);
generator->generate_expression(generator, list_arg, EXPRESSION_GET_ADDRESS);
generator->asm_push("mov dword [ebx], 0");
generator->asm_push("; va_end end for %s", list_arg->sval);

struct datatype void_datatype;
datatype_set_void(&void_datatype);
generator->ret(&void_datatype, "0");
}

void preprocessor_stdarg_include(
struct preprocessor *preprocessor,
struct preprocessor_included_file *included_file) {
#warning "create va_list"
native_create_function(
preprocessor->compiler, "test",
&(struct native_function_callbacks){.call = native_test_function});
native_create_function(preprocessor->compiler, "va_start",
&(struct native_function_callbacks){
.call = native_va_start,
});

native_create_function(preprocessor->compiler, "__builtin_va_arg",
&(struct native_function_callbacks){
.call = native_builtin_va_arg,
});

native_create_function(preprocessor->compiler, "va_end",
&(struct native_function_callbacks){
.call = native_va_end,
});
}
11 changes: 11 additions & 0 deletions rc_includes/stdarg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef STDARG_H
#define STDARG_H

#include <stdarg_internal.h>

typedef int __builtin_va_list;
typedef __builtin_va_list va_list;

#define va_arg(ap, type) __builtin_va_arg(ap, sizeof(type))

#endif // STDARG_H
16 changes: 14 additions & 2 deletions test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
#include <stdarg_internal.h>
#include <stdarg.h>

int main() { test(); }
int sum(int num, ...) {
int res = 0;
va_list args;
va_start(args, num);
int i;
for (i = 0; i < num; i++) {
res += va_arg(args, int);
}
va_end(args);
return res;
}

int main() { return sum(10, 20, 30); }

0 comments on commit e765795

Please sign in to comment.