Skip to content

Commit

Permalink
Merge container support branch into main (#15)
Browse files Browse the repository at this point in the history
See #15 and "extns" branch for history.
  • Loading branch information
sgraham authored Nov 5, 2023
1 parent 3cda30d commit a83b0ee
Show file tree
Hide file tree
Showing 17 changed files with 2,995 additions and 30 deletions.
1,316 changes: 1,316 additions & 0 deletions include/all/_map.h

Large diffs are not rendered by default.

1,214 changes: 1,214 additions & 0 deletions include/all/_vec.h

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions src/dyibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ typedef struct FilePtrArray {
int len;
} FilePtrArray;

typedef struct TokenPtrArray {
Token** data;
int capacity;
int len;
} TokenPtrArray;

typedef struct IntIntInt {
int a;
int b;
Expand All @@ -164,6 +170,7 @@ IMPLSTATIC unsigned int get_page_size(void);
IMPLSTATIC void strarray_push(StringArray* arr, char* s, AllocLifetime lifetime);
IMPLSTATIC void strintarray_push(StringIntArray* arr, StringInt item, AllocLifetime lifetime);
IMPLSTATIC void fileptrarray_push(FilePtrArray* arr, File* item, AllocLifetime lifetime);
IMPLSTATIC void tokenptrarray_push(TokenPtrArray* arr, Token* item, AllocLifetime lifetime);
#if X64WIN
IMPLSTATIC void intintintarray_push(IntIntIntArray* arr, IntIntInt item, AllocLifetime lifetime);
#endif
Expand Down Expand Up @@ -252,6 +259,7 @@ IMPLSTATIC void init_macros(void);
IMPLSTATIC void define_macro(char* name, char* buf);
IMPLSTATIC void undef_macro(char* name);
IMPLSTATIC Token* preprocess(Token* tok);
IMPLSTATIC Token* add_container_instantiations(Token* tok);

//
// parse.c
Expand Down Expand Up @@ -507,6 +515,7 @@ struct Type {
Member* members;
bool is_flexible;
bool is_packed;
Token* methodcall_prefix;

// Function type
Type* return_ty;
Expand Down Expand Up @@ -706,6 +715,9 @@ typedef struct CompilerState {
HashMap preprocess__macros;
CondIncl* preprocess__cond_incl;
HashMap preprocess__pragma_once;
HashMap preprocess__container_included;
TokenPtrArray preprocess__container_tokens;

int preprocess__include_next_idx;
HashMap preprocess__include_path_cache;
HashMap preprocess__include_guards;
Expand Down
1 change: 1 addition & 0 deletions src/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ static void* get_standard_runtime_function(char* name) {
X(atan);
X(atan2);
X(atoi);
X(calloc);
X(ceil);
X(cos);
X(cosh);
Expand Down
9 changes: 5 additions & 4 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ static void print_tokens(Token* tok) {
int line = 1;
for (; tok->kind != TK_EOF; tok = tok->next) {
if (line > 1 && tok->at_bol)
logout("\n");
printf("\n");
if (tok->has_space && !tok->at_bol)
logout(" ");
logout("%.*s", tok->len, tok->loc);
printf(" ");
printf("%.*s", tok->len, tok->loc);
line++;
}
logout("\n");
printf("\n");
}
#endif

Expand Down Expand Up @@ -250,6 +250,7 @@ bool dyibicc_update(DyibiccContext* context, char* filename, char* contents) {
if (!tok)
error("%s: %s", C(base_file), strerror(errno));
tok = preprocess(tok);
tok = add_container_instantiations(tok);

codegen_init(); // Initializes dynasm so that parse() can assign labels.

Expand Down
72 changes: 64 additions & 8 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static Member* get_struct_member(Type* ty, Token* tok);
static Type* struct_decl(Token** rest, Token* tok);
static Type* union_decl(Token** rest, Token* tok);
static Node* postfix(Token** rest, Token* tok);
static Node* funcall(Token** rest, Token* tok, Node* node);
static Node* funcall(Token** rest, Token* tok, Node* node, Node* injected_self);
static Node* unary(Token** rest, Token* tok);
static Node* primary(Token** rest, Token* tok);
static Token* parse_typedef(Token* tok, Type* basety);
Expand Down Expand Up @@ -2699,6 +2699,8 @@ static void struct_members(Token** rest, Token* tok, Type* ty) {
}

// attribute = ("__attribute__" "(" "(" "packed" ")" ")")*
// = ("__attribute__" "(" "(" "aligned" "(" N ")" ")" ")")*
// = ("__attribute__" "(" "(" "methodcall" "(" prefix ")" ")" ")")*
static Token* attribute_list(Token* tok, Type* ty) {
while (consume(&tok, tok, "__attribute__")) {
tok = skip(tok, "(");
Expand All @@ -2716,6 +2718,13 @@ static Token* attribute_list(Token* tok, Type* ty) {
continue;
}

if (consume(&tok, tok, "methodcall")) {
tok = skip(tok, "(");
ty->methodcall_prefix = tok;
tok = skip(tok->next, ")");
continue;
}

if (consume(&tok, tok, "aligned")) {
tok = skip(tok, "(");
ty->align = (int)const_expr(&tok, tok);
Expand Down Expand Up @@ -2875,7 +2884,7 @@ static Member* get_struct_member(Type* ty, Token* tok) {
static Node* struct_ref(Node* node, Token* tok) {
add_type(node);
if (node->ty->kind != TY_STRUCT && node->ty->kind != TY_UNION)
error_tok(node->tok, "not a struct nor a union");
error_tok(node->tok, "neither a struct nor a union");

Type* ty = node->ty;

Expand All @@ -2892,6 +2901,33 @@ static Node* struct_ref(Node* node, Token* tok) {
return node;
}

static Node* methodcall_ref(Token** rest, Token* tok, Node* node) {
add_type(node);
if (node->ty->kind == TY_PTR) {
node = new_unary(ND_DEREF, node, tok);
return methodcall_ref(rest, tok, node);
}

add_type(node);
if (node->ty->kind != TY_STRUCT && node->ty->kind != TY_UNION)
error_tok(node->tok, "neither a struct nor a union");
if (!node->ty->methodcall_prefix)
error_tok(node->tok, "not an __attribute__((methodcall(prefix))) type");

Token* built_prefix = tokenize(
new_file(tok->file->name, format(AL_Compile, "%.*s%.*s", node->ty->methodcall_prefix->len,
node->ty->methodcall_prefix->loc, tok->len, tok->loc)));
built_prefix->line_no = tok->line_no;

Token* unused;
Node* funcnode = primary(&unused, built_prefix);

Node* self = new_unary(ND_ADDR, node, tok);

*rest = tok->next->next;
return funcall(rest, tok->next->next, funcnode, self);
}

// Convert A++ to `(typeof A)((A += 1) - 1)`
static Node* new_inc_dec(Node* node, Token* tok, int addend) {
add_type(node);
Expand Down Expand Up @@ -2933,7 +2969,7 @@ static Node* postfix(Token** rest, Token* tok) {

for (;;) {
if (equal(tok, "(")) {
node = funcall(&tok, tok->next, node);
node = funcall(&tok, tok->next, node, NULL);
continue;
}

Expand All @@ -2952,6 +2988,12 @@ static Node* postfix(Token** rest, Token* tok) {
continue;
}

if (equal(tok, "..")) {
// v..func(...) is short for methodcall_prefix##func(&v, ...)
node = methodcall_ref(&tok, tok->next, node);
continue;
}

if (equal(tok, "->")) {
// x->y is short for (*x).y
node = new_unary(ND_DEREF, node, tok);
Expand Down Expand Up @@ -2982,7 +3024,7 @@ static Node* postfix(Token** rest, Token* tok) {
}

// funcall = (assign ("," assign)*)? ")"
static Node* funcall(Token** rest, Token* tok, Node* fn) {
static Node* funcall(Token** rest, Token* tok, Node* fn, Node* injected_self) {
add_type(fn);

if (fn->ty->kind != TY_FUNC && (fn->ty->kind != TY_PTR || fn->ty->base->kind != TY_FUNC))
Expand All @@ -2994,11 +3036,25 @@ static Node* funcall(Token** rest, Token* tok, Node* fn) {
Node head = {0};
Node* cur = &head;

while (!equal(tok, ")")) {
if (cur != &head)
tok = skip(tok, ",");
while (!equal(tok, ")") || injected_self) {
if (cur != &head) {
if (injected_self) {
injected_self = NULL;
if (equal(tok, ")"))
break;
} else {
tok = skip(tok, ",");
}
}

Node* arg = assign(&tok, tok);
Node* arg;

if (injected_self) {
arg = injected_self;
// cleared on next loop, instead of skipping comma above.
} else {
arg = assign(&tok, tok);
}
add_type(arg);

if (!param_ty && !ty->is_variadic)
Expand Down
Loading

0 comments on commit a83b0ee

Please sign in to comment.