-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.c
executable file
·143 lines (127 loc) · 3.84 KB
/
main.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
142
143
#include <stdio.h>
#include "lex.h"
#include "expr.h"
#include "decl.h"
#include "stmt.h"
#include "emit.h"
#include "func.h"
static const char *srcCode = "{int (*f(int,int,int))[4];}";
static char NextCharFromMem(void)
{
int ch = *srcCode;
srcCode++;
if (ch == 0)
{
return (char)EOF_CH;
}
else
{
return (char)ch;
}
}
/**
* @brief 被翻译代码在标准输入当中,此函数每次读取被翻译代码当中的一个字符
*
* @return char 代码当中的一个字符。
*/
static char NextCharFromStdin(void)
{
int ch = fgetc(stdin); // 从标准输入当中读取一个字符
if (ch == EOF) // EOF 是 -1
{
return (char)EOF_CH;
}
else // 将读入的字符返回。
{
return (char)ch;
}
}
/**
* @brief 调用来生成客制化定义库函数对应的汇编语言。由attach_our_library(main.c)调用,生成汇编SQAless, SQAlarger, SQAequal。
*
* @param setCmd 汇编对应执行我们客制化库函数的汇编指令。例如 setl
* @param funcName 例如 call SQAless,funcName是SQAless
*/
static void output_library_func(char *setCmd, char *funcName)
{
EmitLabel("\n.text");
EmitLabel(".globl %s", funcName);
EmitLabel("%s:", funcName);
EmitAssembly("movl 8(%%esp), %%eax");
EmitAssembly("cmpl %%eax, 4(%%esp)");
EmitAssembly("%s %%al", setCmd);
EmitAssembly("movzbl %%al, %%eax");
EmitAssembly("ret");
}
/**
* @brief 生成客制化定义库函数对应的汇编码。调用函数生成SQAless, SQAlarger, SQAequal。并且额外实现SQAstore, SQAload汇编码逻辑。
*
*/
static void attach_our_library(void)
{
output_library_func("setl", "SQAless");
output_library_func("setg", "SQAlarger");
output_library_func("sete", "SQAequal");
/**
* @brief 生成SQAstore汇编码:
*
*/
EmitLabel("\n.text");
EmitLabel(".globl %s", "SQAstore");
EmitLabel("%s:", "SQAstore");
EmitAssembly("movl 12(%%esp), %%eax");
EmitAssembly("movl 4(%%esp), %%ecx");
EmitAssembly("movl 8(%%esp), %%edx");
EmitAssembly("movl %%eax, (%%ecx,%%edx)");
EmitAssembly("ret");
/**
* @brief 生成SQAload汇编码:
*
*/
EmitLabel("\n.text");
EmitLabel(".globl %s", "SQAload");
EmitLabel("%s:", "SQAload");
EmitAssembly("movl 4(%%esp), %%edx");
EmitAssembly("movl 8(%%esp), %%eax");
EmitAssembly("movl (%%edx,%%eax), %%eax");
EmitAssembly("ret");
}
/**
* @brief Declarations()执行词法分词, FunctionDefinitions()执行语法分析。语法词法分析结束之后,
*/
int main()
{
AstStmtNodePtr declarations = NULL; // 抽象语法树变量声明节点
AstFuncDefNodePtr functions = NULL; // 抽象语法树函数声明节点
/**
* @brief NextCharFromStdin(): 读取放在标准输入里面的被翻译代码的一个字符,然后
* 传给 Initexer:将lex.c的NextChar设置位当前字符。
*/
InitLexer(NextCharFromStdin);
// 读入并且分以一个词法单元,设置该词法单元的类型。设置给lex.h: curToken。
NEXT_TOKEN;
// 变量声明的词法分析 & 函数定义的语法分析
declarations = Declarations();
functions = FunctionDefinitions();
Expect(TK_EOF); // 类C代码文末结束符
// 生成翻译汇编文件的首四行
EmitLabel("#Auto-Genereated by SE352");
EmitLabel(".data");
EmitAssembly("%s: .string \"%%d\"", INPUT_FORMAT_STR_NAME);
EmitAssembly("%s: .string \"%%d\\012\"", OUTPUT_FORMAT_STR_NAME);
// 生成类C代码所有变量声明对应的汇编码
EmitStatementNode(declarations);
/*********************************
.text
.globl main
main:
**********************************/
// 生成自定义库函数的汇编码。由于我们没有 < > = <= >=,因此自定义库函数
attach_our_library();
// 生成类C代码所有函数定义对应的汇编代码
EmitFuncDefNode(functions);
// FIXME: TBD, free the heap memory.
// To be simple, we only use malloc(), but never free() in this simple compiler.
// Let the OS do it for us :)
return 0;
}