forked from DoctorWkt/acwj
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcg.c
141 lines (122 loc) · 3.55 KB
/
cg.c
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "defs.h"
#include "data.h"
#include "decl.h"
// Code generator for x86-64
// Copyright (c) 2019 Warren Toomey, GPL3
// List of available registers and their names
static int freereg[4];
static char *reglist[4] = { "%r8", "%r9", "%r10", "%r11" };
// Set all registers as available
void freeall_registers(void) {
freereg[0] = freereg[1] = freereg[2] = freereg[3] = 1;
}
// Allocate a free register. Return the number of
// the register. Die if no available registers.
static int alloc_register(void) {
for (int i = 0; i < 4; i++) {
if (freereg[i]) {
freereg[i] = 0;
return (i);
}
}
fatal("Out of registers");
}
// Return a register to the list of available registers.
// Check to see if it's not already there.
static void free_register(int reg) {
if (freereg[reg] != 0)
fatald("Error trying to free register", reg);
freereg[reg] = 1;
}
// Print out the assembly preamble
void cgpreamble() {
freeall_registers();
fputs("\t.text\n"
".LC0:\n"
"\t.string\t\"%d\\n\"\n"
"printint:\n"
"\tpushq\t%rbp\n"
"\tmovq\t%rsp, %rbp\n"
"\tsubq\t$16, %rsp\n"
"\tmovl\t%edi, -4(%rbp)\n"
"\tmovl\t-4(%rbp), %eax\n"
"\tmovl\t%eax, %esi\n"
"\tleaq .LC0(%rip), %rdi\n"
"\tmovl $0, %eax\n"
"\tcall printf@PLT\n"
"\tnop\n"
"\tleave\n"
"\tret\n"
"\n"
"\t.globl\tmain\n"
"\t.type\tmain, @function\n"
"main:\n" "\tpushq\t%rbp\n" "\tmovq %rsp, %rbp\n", Outfile);
}
// Print out the assembly postamble
void cgpostamble() {
fputs("\tmovl $0, %eax\n" "\tpopq %rbp\n" "\tret\n", Outfile);
}
// Load an integer literal value into a register.
// Return the number of the register
int cgloadint(int value) {
// Get a new register
int r = alloc_register();
// Print out the code to initialise it
fprintf(Outfile, "\tmovq\t$%d, %s\n", value, reglist[r]);
return (r);
}
// Load a value from a variable into a register.
// Return the number of the register
int cgloadglob(char *identifier) {
// Get a new register
int r = alloc_register();
// Print out the code to initialise it
fprintf(Outfile, "\tmovq\t%s(\%%rip), %s\n", identifier, reglist[r]);
return (r);
}
// Add two registers together and return
// the number of the register with the result
int cgadd(int r1, int r2) {
fprintf(Outfile, "\taddq\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r1);
return (r2);
}
// Subtract the second register from the first and
// return the number of the register with the result
int cgsub(int r1, int r2) {
fprintf(Outfile, "\tsubq\t%s, %s\n", reglist[r2], reglist[r1]);
free_register(r2);
return (r1);
}
// Multiply two registers together and return
// the number of the register with the result
int cgmul(int r1, int r2) {
fprintf(Outfile, "\timulq\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r1);
return (r2);
}
// Divide the first register by the second and
// return the number of the register with the result
int cgdiv(int r1, int r2) {
fprintf(Outfile, "\tmovq\t%s,%%rax\n", reglist[r1]);
fprintf(Outfile, "\tcqo\n");
fprintf(Outfile, "\tidivq\t%s\n", reglist[r2]);
fprintf(Outfile, "\tmovq\t%%rax,%s\n", reglist[r1]);
free_register(r2);
return (r1);
}
// Call printint() with the given register
void cgprintint(int r) {
fprintf(Outfile, "\tmovq\t%s, %%rdi\n", reglist[r]);
fprintf(Outfile, "\tcall\tprintint\n");
free_register(r);
}
// Store a register's value into a variable
int cgstorglob(int r, char *identifier) {
fprintf(Outfile, "\tmovq\t%s, %s(\%%rip)\n", reglist[r], identifier);
return (r);
}
// Generate a global symbol
void cgglobsym(char *sym) {
fprintf(Outfile, "\t.comm\t%s,8,8\n", sym);
}