summaryrefslogtreecommitdiff
path: root/ir.h
blob: 935186451823b2af9fc019fb665050779fe4e390 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#ifndef IR_H
#define IR_H

#include "arena.h"
#include "dynarr.h"
#include "lex.h" /* for error reporting only */
#include "str.h"

/* nodes */

typedef enum {
	N_START,
	N_RETURN,
	N_KEEPALIVE,
	N_LIT,
	N_OP_ADD, N_OP_SUB, N_OP_MUL, N_OP_DIV,
	N_OP_AND, N_OP_OR, N_OP_XOR,
	N_OP_SHL, N_OP_SHR,
	N_OP_NEG, N_OP_NOT,
	N_VALUE
} NodeType;

const char *node_type_name(NodeType t);

typedef enum {
	T_BOT,
	T_TOP,
	T_CONST,
	T_INT
} Type;

typedef struct {
	Type type;
	union {
		int64_t i;
		uint64_t u;
	};
} Value;

typedef struct Node {
	union {
		struct Node *prev_free;
		struct {
			int id, refs;
			int walked;
			NodeType type;
			LexSpan src_pos;
			DYNARR(struct Node *) in, out;
			Value val;
		};
	};
} Node;

/* procedure graph */

typedef struct NameBinding {
	struct NameBinding *prev;
	LexSpan src_pos;
	Str name;
	Node *node;
} NameBinding;

typedef struct ScopeFrame {
	struct ScopeFrame *prev;
	NameBinding *latest;
} ScopeFrame;

typedef struct {
	ScopeFrame *tail, *free_scope;
	NameBinding *free_bind;
} Scope;

typedef struct {
	Arena arena;
	Str name;
	Node *start, *stop, *keepalive;
	Node *free_list;
	Scope scope;
} Proc;

void node_kill(Node *n, Proc *p);
void node_die(Node *n, Proc *p);
void node_del_out(Node *n, Node *p);
void node_del_in(Node *n, Node *p);
void node_kill(Node *n, Proc *p);
void node_add(Proc *p, Node *src, Node *dest);
void node_remove(Proc *p, Node *src, Node *dest);
Node *node_new_empty(Proc *p, NodeType t);
Node *node_newv(Proc *p, NodeType t, ...);
Node *node_dedup_lit(Proc *p, Value v);
Node *node_new_lit_i64(Proc *p, int64_t i);
Value node_compute(Node *n, Lexer *l);
Node *node_peephole(Node *n, Proc *p, Lexer *l);

#define node_new(...) node_newv(__VA_ARGS__, NULL)

void proc_init(Proc *proc, Str name);
void proc_free(Proc *proc);

ScopeFrame *scope_push(Scope *scope, Proc *proc);
ScopeFrame *scope_pop(Scope *scope, Proc *proc);
NameBinding *scope_find(Scope *scope, Str name);
NameBinding *scope_bind(Scope *scope, Str name, Node *value, LexSpan pos, Proc *proc);
NameBinding *scope_update(Scope *scope, Str name, Node *to, Proc *proc);

#endif