parent
a59efbf0e2
commit
36f4d12287
@ -0,0 +1,3 @@
|
||||
.vscode
|
||||
build
|
||||
|
@ -0,0 +1,37 @@
|
||||
project(SysYFCompiler)
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -Wall -Wextra -Wno-unused -Wshadow -Werror -g -pedantic")
|
||||
|
||||
# include generated files in project environment
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/AST)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ErrorReporter)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/Frontend)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/SysYFIR)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/SysYFIRBuilder)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/AST)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/ErrorReporter)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/Frontend)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/SysYFIR)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/SysYFIRBuilder)
|
||||
|
||||
add_executable(
|
||||
SysYFCompiler
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
SysYFCompiler
|
||||
SysYFIRBuilder
|
||||
IRLib
|
||||
Driver
|
||||
ASTPrinter
|
||||
ErrReporter
|
||||
)
|
@ -0,0 +1,28 @@
|
||||
int num[2] = {4, 8};
|
||||
int x[1];
|
||||
int n;
|
||||
int tmp = 1;
|
||||
|
||||
int climbStairs(int n) {
|
||||
if(n < 4)
|
||||
return n;
|
||||
int dp[10];
|
||||
dp[0] = 0;
|
||||
dp[1] = 1;
|
||||
dp[2] = 2;
|
||||
int i;
|
||||
i = 3;
|
||||
while(i<n+1){
|
||||
dp[i] = dp[i-1] + dp[i-2];
|
||||
i = i + 1;
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
int main(){
|
||||
int res;
|
||||
n=num[0];
|
||||
x[0] = num[tmp];
|
||||
res = climbStairs(n + tmp);
|
||||
return res - x[0];
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
; 中间代码头部尾部参考clang -S -emit-llvm 生成结果
|
||||
|
||||
; ModuleID = 'func_test.c'
|
||||
source_filename = "func_test.c"
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
define dso_local i32 @add(i32 %0, i32 %1) #0 {
|
||||
%3 = alloca i32, align 4
|
||||
store i32 %0, i32* %3, align 4 ; alloca a
|
||||
|
||||
%4 = alloca i32, align 4
|
||||
store i32 %1, i32* %4, align 4 ; alloca b
|
||||
|
||||
%5 = load i32, i32* %3, align 4
|
||||
%6 = load i32, i32* %4, align 4
|
||||
%7 = add nsw i32 %5, %6 ; a+b
|
||||
%8 = sub nsw i32 %7, 1 ; a+b-1
|
||||
ret i32 %8 ; return a+b-1
|
||||
}
|
||||
|
||||
define dso_local i32 @main() #0 {
|
||||
%1 = alloca i32, align 4
|
||||
%2 = alloca i32, align 4
|
||||
%3 = alloca i32, align 4
|
||||
|
||||
store i32 3, i32* %1, align 4 ; a=3
|
||||
store i32 2, i32* %2, align 4 ; b=2
|
||||
store i32 5, i32* %3, align 4 ; c=5
|
||||
|
||||
|
||||
%4 = load i32, i32* %1, align 4
|
||||
%5 = load i32, i32* %2, align 4
|
||||
%6 = load i32, i32* %3, align 4
|
||||
|
||||
%7 = call i32 @add(i32 %4, i32 %5) ; add(a, b)
|
||||
%8 = add nsw i32 %6, %7 ; c+add(a,b)
|
||||
ret i32 %8
|
||||
}
|
||||
|
||||
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3, !4}
|
||||
!llvm.ident = !{!5}
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 7, !"PIC Level", i32 2}
|
||||
!2 = !{i32 7, !"PIE Level", i32 2}
|
||||
!3 = !{i32 7, !"uwtable", i32 1}
|
||||
!4 = !{i32 7, !"frame-pointer", i32 2}
|
||||
!5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"}
|
@ -0,0 +1,6 @@
|
||||
int main(){
|
||||
float b = 1.8;
|
||||
int a[2] = {2};
|
||||
a[1] = a[0] * b;
|
||||
return a[1];
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
int add(int a,int b){
|
||||
return (a+b-1);
|
||||
}
|
||||
|
||||
int main(){
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
a=3;
|
||||
b=2;
|
||||
c = 5;
|
||||
return c + add(a,b);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
int a;
|
||||
|
||||
int main(){
|
||||
a = 10;
|
||||
if( a>0 ){
|
||||
return a;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
int a;
|
||||
int b;
|
||||
int main(){
|
||||
b=0;
|
||||
a=3;
|
||||
while(a>0){
|
||||
b = b+a;
|
||||
a = a-1;
|
||||
}
|
||||
return b;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
project(task2)
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -Wall -g -pedantic")
|
||||
|
||||
set(SYSYF_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# include generated files in project environment
|
||||
include_directories(${SYSYF_SOURCE_DIR}include)
|
||||
include_directories(${SYSYF_SOURCE_DIR}include/SysYFIR)
|
||||
add_subdirectory(${SYSYF_SOURCE_DIR}src/SysYFIR src/SysYFIR)
|
||||
|
||||
add_subdirectory(demo)
|
||||
add_subdirectory(cpp)
|
@ -0,0 +1,36 @@
|
||||
add_executable(
|
||||
assign_generator
|
||||
assign_gen.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
assign_generator
|
||||
IRLib
|
||||
)
|
||||
|
||||
add_executable(
|
||||
func_generator
|
||||
func_gen.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
func_generator
|
||||
IRLib
|
||||
)
|
||||
|
||||
add_executable(
|
||||
if_generator
|
||||
if_gen.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
if_generator
|
||||
IRLib
|
||||
)
|
||||
|
||||
add_executable(
|
||||
while_generator
|
||||
while_gen.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
while_generator
|
||||
IRLib
|
||||
)
|
||||
|
@ -0,0 +1,3 @@
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
add_executable(
|
||||
go_upstairs_generator
|
||||
go_upstairs_gen.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
go_upstairs_generator
|
||||
IRLib
|
||||
)
|
@ -0,0 +1,28 @@
|
||||
int num[2] = {4, 8};
|
||||
int x[1];
|
||||
int n;
|
||||
int tmp = 1;
|
||||
|
||||
int climbStairs(int n) {
|
||||
if(n < 4)
|
||||
return n;
|
||||
int dp[10];
|
||||
dp[0] = 0;
|
||||
dp[1] = 1;
|
||||
dp[2] = 2;
|
||||
int i;
|
||||
i = 3;
|
||||
while(i<n+1){
|
||||
dp[i] = dp[i-1] + dp[i-2];
|
||||
i = i + 1;
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
int main(){
|
||||
int res;
|
||||
n=num[0];
|
||||
x[0] = num[tmp];
|
||||
res = climbStairs(n + tmp);
|
||||
return res - x[0];
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
int main(){
|
||||
float b = 1.8;
|
||||
int a[2] = {2};
|
||||
a[1] = a[0] * b;
|
||||
return a[1];
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
int add(int a,int b){
|
||||
return (a+b-1);
|
||||
}
|
||||
|
||||
int main(){
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
a=3;
|
||||
b=2;
|
||||
c = 5;
|
||||
return c + add(a,b);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
int a;
|
||||
|
||||
int main(){
|
||||
a = 10;
|
||||
if( a>0 ){
|
||||
return a;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
int a;
|
||||
int b;
|
||||
int main(){
|
||||
b=0;
|
||||
a=3;
|
||||
while(a>0){
|
||||
b = b+a;
|
||||
a = a-1;
|
||||
}
|
||||
return b;
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
IRBuild_ptn = '"{}" "-emit-ir" "-o" "{}" "{}"'
|
||||
ExeGen_ptn = '"clang" "{}" "-o" "{}" "{}" "../../lib/lib.c"'
|
||||
Exe_ptn = '"{}"'
|
||||
|
||||
def eval(EXE_PATH, TEST_BASE_PATH, optimization):
|
||||
print('===========TEST START===========')
|
||||
print('now in {}'.format(TEST_BASE_PATH))
|
||||
dir_succ = True
|
||||
for case in testcases:
|
||||
print('Case %s:' % case, end='')
|
||||
TEST_PATH = TEST_BASE_PATH + case
|
||||
SY_PATH = TEST_BASE_PATH + case + '.sy'
|
||||
LL_PATH = TEST_BASE_PATH + case + '.ll'
|
||||
INPUT_PATH = TEST_BASE_PATH + case + '.in'
|
||||
OUTPUT_PATH = TEST_BASE_PATH + case + '.out'
|
||||
need_input = testcases[case]
|
||||
|
||||
IRBuild_result = subprocess.run(IRBuild_ptn.format(EXE_PATH, LL_PATH, SY_PATH), shell=True, stderr=subprocess.PIPE)
|
||||
if IRBuild_result.returncode == 0:
|
||||
input_option = None
|
||||
if need_input:
|
||||
with open(INPUT_PATH, "rb") as fin:
|
||||
input_option = fin.read()
|
||||
|
||||
try:
|
||||
subprocess.run(ExeGen_ptn.format(optimization, TEST_PATH, LL_PATH), shell=True, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(Exe_ptn.format(TEST_PATH), shell=True, input=input_option, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out = result.stdout.split(b'\n')
|
||||
if result.returncode != b'':
|
||||
out.append(str(result.returncode).encode())
|
||||
for i in range(len(out)-1, -1, -1):
|
||||
out[i] = out[i].strip(b'\r')
|
||||
if out[i] == b'':
|
||||
out.remove(b'')
|
||||
case_succ = True
|
||||
with open(OUTPUT_PATH, "rb") as fout:
|
||||
i = 0
|
||||
for line in fout.readlines():
|
||||
line = line.strip(b'\r').strip(b'\n')
|
||||
if line == '':
|
||||
continue
|
||||
if out[i] != line:
|
||||
dir_succ = False
|
||||
case_succ = False
|
||||
i = i + 1
|
||||
if case_succ:
|
||||
print('\t\033[32mPass\033[0m')
|
||||
else:
|
||||
print('\t\033[31mWrong Answer\033[0m')
|
||||
except Exception as _:
|
||||
dir_succ = False
|
||||
print(_, end='')
|
||||
print('\t\033[31mCodeGen or CodeExecute Fail\033[0m')
|
||||
finally:
|
||||
subprocess.call(["rm", "-rf", TEST_PATH, TEST_PATH])
|
||||
subprocess.call(["rm", "-rf", TEST_PATH, TEST_PATH + ".o"])
|
||||
subprocess.call(["rm", "-rf", TEST_PATH, TEST_PATH + ".ll"])
|
||||
|
||||
else:
|
||||
dir_succ = False
|
||||
print('\t\033[31mIRBuild Fail\033[0m')
|
||||
if dir_succ:
|
||||
print('\t\033[32mSuccess\033[0m in dir {}'.format(TEST_BASE_PATH))
|
||||
else:
|
||||
print('\t\033[31mFail\033[0m in dir {}'.format(TEST_BASE_PATH))
|
||||
|
||||
print('============TEST END============')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# you can only modify this to add your testcase
|
||||
TEST_DIRS = [
|
||||
'./test/',
|
||||
]
|
||||
# you can only modify this to add your testcase
|
||||
|
||||
optimization = "-O0" # -O0 -O1 -O2 -O3 -O4(currently = -O3) -Ofast
|
||||
for TEST_BASE_PATH in TEST_DIRS:
|
||||
testcases = {} # { name: need_input }
|
||||
EXE_PATH = os.path.abspath('../../build/SysYFCompiler')
|
||||
testcase_list = list(map(lambda x: x.split('.'), os.listdir(TEST_BASE_PATH)))
|
||||
testcase_list.sort()
|
||||
for i in range(len(testcase_list)):
|
||||
testcases[testcase_list[i][0]] = False
|
||||
for i in range(len(testcase_list)):
|
||||
testcases[testcase_list[i][0]] = testcases[testcase_list[i][0]] | (testcase_list[i][1] == 'in')
|
||||
eval(EXE_PATH, TEST_BASE_PATH, optimization=optimization)
|
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1,3 @@
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
@ -0,0 +1 @@
|
||||
29
|
@ -0,0 +1,8 @@
|
||||
int a,b;
|
||||
|
||||
int main(){
|
||||
a=10;
|
||||
b=5;
|
||||
int c=a*2+b*1.1+3.6;
|
||||
return c;
|
||||
}
|
@ -0,0 +1 @@
|
||||
21
|
@ -0,0 +1,5 @@
|
||||
int main() {
|
||||
int a = 10;
|
||||
;
|
||||
return a * 2 + 1;
|
||||
}
|
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1,4 @@
|
||||
int a[10];
|
||||
int main(){
|
||||
return 0;
|
||||
}
|
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1,5 @@
|
||||
int a[10];
|
||||
int main(){
|
||||
a[0]=1;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1 @@
|
||||
4
|
@ -0,0 +1,5 @@
|
||||
const int x=4;
|
||||
|
||||
int main(){
|
||||
return x;
|
||||
}
|
@ -0,0 +1 @@
|
||||
8
|
@ -0,0 +1,7 @@
|
||||
const int a[5]={0,1,2,3,4};
|
||||
const int b = 3;
|
||||
float c = a[b + 1];
|
||||
|
||||
int main(){
|
||||
return a[4] + c;
|
||||
}
|
@ -0,0 +1 @@
|
||||
4
|
@ -0,0 +1,8 @@
|
||||
int defn(){
|
||||
return 4;
|
||||
}
|
||||
|
||||
int main(){
|
||||
int a=defn();
|
||||
return a;
|
||||
}
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,13 @@
|
||||
int a,b,c;
|
||||
|
||||
void add(int a,int b){
|
||||
c=a+b;
|
||||
return;
|
||||
}
|
||||
|
||||
int main(){
|
||||
a=3;
|
||||
b=2;
|
||||
add(a,b);
|
||||
return c;
|
||||
}
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
int a;
|
||||
|
||||
int main(){
|
||||
a = 10;
|
||||
if( a>0 ){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,10 @@
|
||||
int a;
|
||||
int main(){
|
||||
a = 10;
|
||||
if( a>0 ){
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
6
|
@ -0,0 +1,11 @@
|
||||
int a;
|
||||
int b;
|
||||
int main(){
|
||||
b=0;
|
||||
a=3;
|
||||
while(a>0){
|
||||
b = b+a;
|
||||
a = a-1;
|
||||
}
|
||||
return b;
|
||||
}
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,9 @@
|
||||
int main(){
|
||||
int a=10;
|
||||
while(a>0){
|
||||
a=a-1;
|
||||
if(a==5)
|
||||
break;
|
||||
}
|
||||
return a;
|
||||
}
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,11 @@
|
||||
int main(){
|
||||
int a=10;
|
||||
while(a>0){
|
||||
if(a>5){
|
||||
a=a-1;
|
||||
continue;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return a;
|
||||
}
|
@ -0,0 +1 @@
|
||||
10
|
@ -0,0 +1 @@
|
||||
10
|
@ -0,0 +1,5 @@
|
||||
int main(){
|
||||
int a;
|
||||
a = getint();
|
||||
return a;
|
||||
}
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,23 @@
|
||||
int a;
|
||||
|
||||
int myFunc(int a, int b, int c) {
|
||||
a = 2;
|
||||
{
|
||||
int c;
|
||||
c = 0;
|
||||
if (c != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (b > 0) {
|
||||
b = b - 1;
|
||||
}
|
||||
return (a)+(b);
|
||||
}
|
||||
|
||||
int main() {
|
||||
a = (3);
|
||||
int b;
|
||||
b = myFunc(1, 2, 1);
|
||||
return ((a+b));
|
||||
}
|
@ -0,0 +1 @@
|
||||
3 2
|
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1,12 @@
|
||||
int a;
|
||||
int b;
|
||||
int main(){
|
||||
a = getint();
|
||||
b = getint();
|
||||
if ( a == b ){
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
8
|
@ -0,0 +1,17 @@
|
||||
const int a = 5;
|
||||
int b;
|
||||
|
||||
int my_sum(int x, float y){
|
||||
b = a + x - y;
|
||||
return b;
|
||||
}
|
||||
|
||||
int main(){
|
||||
int a = 7;
|
||||
{
|
||||
const float a = 3.3;
|
||||
my_sum(a, a);
|
||||
}
|
||||
my_sum(a, b);
|
||||
return b;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
4
|
||||
20
|
@ -0,0 +1 @@
|
||||
4
|
@ -0,0 +1,34 @@
|
||||
int n;
|
||||
|
||||
int gcd(int m,int n)
|
||||
{
|
||||
int t;
|
||||
int r;
|
||||
|
||||
if(m<n) { t=m;m=n;n=t; }
|
||||
|
||||
r=m%n;
|
||||
|
||||
while(r!=0)
|
||||
{
|
||||
m=n;
|
||||
n=r;
|
||||
r=m%n;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//newline=10;
|
||||
int i;
|
||||
int m;
|
||||
//m = 1478;
|
||||
//int t;
|
||||
i=getint();
|
||||
m=getint();
|
||||
|
||||
return gcd(i,m);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
4
|
||||
4
|
||||
7
|
||||
3
|
||||
9
|
@ -0,0 +1,5 @@
|
||||
1 2, 1 3, 2 3, 1 2, 3 1, 3 2, 1 2, 1 3, 2 3, 2 1, 3 1, 2 3, 1 2, 1 3, 2 3,
|
||||
1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3,
|
||||
1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3,
|
||||
1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 3 1, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 1 2, 3 2, 3 1, 2 1, 3 2, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3, 2 1, 3 2, 3 1, 2 1, 2 3, 1 3, 1 2, 3 2, 1 3, 2 1, 2 3, 1 3,
|
||||
0
|
@ -0,0 +1,27 @@
|
||||
|
||||
void move(int x, int y)
|
||||
{
|
||||
putint(x); putch(32); putint(y); putch(44); putch(32);
|
||||
}
|
||||
|
||||
void hanoi(int n, int one, int two, int three)
|
||||
{
|
||||
if (n == 1)
|
||||
move(one, three);
|
||||
else {
|
||||
hanoi(n - 1, one, three, two);
|
||||
move(one, three);
|
||||
hanoi(n - 1, two, one, three);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int n = getint();
|
||||
while (n > 0) {
|
||||
hanoi(getint(), 1, 2, 3);
|
||||
putch(10);
|
||||
n = n - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
@ -0,0 +1,330 @@
|
||||
#ifndef _SYSYF_SYNTAX_TREE_H_
|
||||
#define _SYSYF_SYNTAX_TREE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "location.hh"
|
||||
#include "internal_types.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace SyntaxTree
|
||||
{
|
||||
|
||||
using Position = yy::location;
|
||||
|
||||
// Enumerations
|
||||
enum class Type
|
||||
{
|
||||
INT = 0,
|
||||
VOID,
|
||||
STRING,
|
||||
BOOL,
|
||||
FLOAT
|
||||
};
|
||||
|
||||
enum class BinOp
|
||||
{
|
||||
PLUS = 0,
|
||||
MINUS,
|
||||
MULTIPLY,
|
||||
DIVIDE,
|
||||
MODULO
|
||||
};
|
||||
|
||||
enum class UnaryOp
|
||||
{
|
||||
PLUS = 0,
|
||||
MINUS
|
||||
};
|
||||
|
||||
enum class UnaryCondOp
|
||||
{
|
||||
NOT = 0
|
||||
};
|
||||
|
||||
enum class BinaryCondOp
|
||||
{
|
||||
LT = 0,
|
||||
LTE,
|
||||
GT,
|
||||
GTE,
|
||||
EQ,
|
||||
NEQ,
|
||||
LAND,
|
||||
LOR
|
||||
};
|
||||
|
||||
// Forward declaration
|
||||
struct Node;
|
||||
struct Assembly;
|
||||
struct GlobalDef;
|
||||
struct FuncDef;
|
||||
|
||||
struct Expr;
|
||||
struct CondExpr;
|
||||
struct AddExpr;
|
||||
struct BinaryExpr;
|
||||
struct BinaryCondExpr;
|
||||
struct UnaryCondExpr;
|
||||
struct UnaryExpr;
|
||||
struct LVal;
|
||||
struct Literal;
|
||||
|
||||
struct Stmt;
|
||||
struct VarDef;
|
||||
struct AssignStmt;
|
||||
struct FuncCallStmt;
|
||||
struct ReturnStmt;
|
||||
struct BlockStmt;
|
||||
struct EmptyStmt;
|
||||
struct ExprStmt;
|
||||
|
||||
struct FuncParam;
|
||||
struct FuncFParamList;
|
||||
|
||||
struct IfStmt;
|
||||
struct WhileStmt;
|
||||
struct BreakStmt;
|
||||
struct ContinueStmt;
|
||||
struct InitVal;
|
||||
|
||||
class Visitor;
|
||||
|
||||
// Virtual base of all kinds of syntax tree nodes.
|
||||
struct Node
|
||||
{
|
||||
Position loc;
|
||||
// Used in Visitor. Irrelevant to syntax tree generation.
|
||||
virtual void accept(Visitor &visitor) = 0;
|
||||
};
|
||||
|
||||
//node for initial value
|
||||
struct InitVal: Node{
|
||||
bool isExp;
|
||||
PtrVec<InitVal> elementList;
|
||||
//std::vector<Ptr<InitVal>> elementList;
|
||||
Ptr<Expr> expr;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Root node of an ordinary syntax tree.
|
||||
struct Assembly : Node
|
||||
{
|
||||
PtrVec<GlobalDef> global_defs;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Virtual base of global definitions, function or variable one.
|
||||
struct GlobalDef : virtual Node
|
||||
{
|
||||
void accept(Visitor &visitor) override = 0;
|
||||
};
|
||||
|
||||
// Function definition.
|
||||
struct FuncDef : GlobalDef
|
||||
{
|
||||
Type ret_type;
|
||||
Ptr<FuncFParamList> param_list;
|
||||
std::string name;
|
||||
Ptr<BlockStmt> body;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Virtual base for statements.
|
||||
struct Stmt : virtual Node
|
||||
{
|
||||
void accept(Visitor &visitor) override = 0;
|
||||
};
|
||||
|
||||
// Variable definition. Multiple of this would be both a statement and a global definition; however, itself only
|
||||
// represents a single variable definition.
|
||||
struct VarDef : Stmt, GlobalDef
|
||||
{
|
||||
bool is_constant;
|
||||
Type btype;
|
||||
std::string name;
|
||||
bool is_inited; // This is used to verify `{}`
|
||||
PtrVec<Expr> array_length; // empty for non-array variables
|
||||
Ptr<InitVal> initializers;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Assignment statement.
|
||||
struct AssignStmt : Stmt
|
||||
{
|
||||
Ptr<LVal> target;
|
||||
Ptr<Expr> value;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Return statement.
|
||||
struct ReturnStmt : Stmt
|
||||
{
|
||||
Ptr<Expr> ret; // nullptr for void return
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// BlockStmt statement.
|
||||
struct BlockStmt : Stmt
|
||||
{
|
||||
PtrVec<Stmt> body;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Empty statement (aka a single ';').
|
||||
struct EmptyStmt : Stmt
|
||||
{
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct ExprStmt : Stmt
|
||||
{
|
||||
Ptr<Expr> exp;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Virtual base of expressions.
|
||||
struct Expr : Node
|
||||
{
|
||||
void accept(Visitor &visitor) override = 0;
|
||||
};
|
||||
|
||||
struct CondExpr : Expr
|
||||
{
|
||||
void accept(Visitor &visitor) override = 0;
|
||||
};
|
||||
|
||||
struct AddExpr : Expr
|
||||
{
|
||||
void accept(Visitor &visitor) override = 0;
|
||||
};
|
||||
|
||||
|
||||
struct UnaryCondExpr : CondExpr{
|
||||
UnaryCondOp op;
|
||||
Ptr<Expr> rhs;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct BinaryCondExpr : CondExpr{
|
||||
BinaryCondOp op;
|
||||
Ptr<Expr> lhs,rhs;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Expression like `lhs op rhs`.
|
||||
struct BinaryExpr : AddExpr
|
||||
{
|
||||
BinOp op;
|
||||
Ptr<Expr> lhs, rhs;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Expression like `op rhs`.
|
||||
struct UnaryExpr : AddExpr
|
||||
{
|
||||
UnaryOp op;
|
||||
Ptr<Expr> rhs;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Expression like `ident` or `ident[exp]`.
|
||||
struct LVal : AddExpr
|
||||
{
|
||||
std::string name;
|
||||
PtrVec<Expr> array_index; // nullptr if not indexed as array
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Expression constructed by a literal number.
|
||||
struct Literal : AddExpr
|
||||
{
|
||||
Type literal_type;
|
||||
int int_const;
|
||||
// std::string str;
|
||||
double float_const;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Function call statement.
|
||||
struct FuncCallStmt : AddExpr
|
||||
{
|
||||
std::string name;
|
||||
PtrVec<Expr> params;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct FuncParam : Node
|
||||
{
|
||||
std::string name;
|
||||
Type param_type;
|
||||
PtrVec<Expr> array_index; // nullptr if not indexed as array
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct FuncFParamList : Node
|
||||
{
|
||||
PtrVec<FuncParam> params;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct IfStmt : Stmt
|
||||
{
|
||||
Ptr<Expr> cond_exp;
|
||||
Ptr<Stmt> if_statement;
|
||||
Ptr<Stmt> else_statement;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct WhileStmt : Stmt
|
||||
{
|
||||
Ptr<Expr> cond_exp;
|
||||
Ptr<Stmt> statement;
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct BreakStmt : Stmt
|
||||
{
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
struct ContinueStmt : Stmt
|
||||
{
|
||||
void accept(Visitor &visitor) final;
|
||||
};
|
||||
|
||||
// Visitor base type
|
||||
class Visitor
|
||||
{
|
||||
public:
|
||||
virtual void visit(Assembly &node) = 0;
|
||||
virtual void visit(FuncDef &node) = 0;
|
||||
virtual void visit(BinaryExpr &node) = 0;
|
||||
virtual void visit(UnaryExpr &node) = 0;
|
||||
virtual void visit(LVal &node) = 0;
|
||||
virtual void visit(Literal &node) = 0;
|
||||
virtual void visit(ReturnStmt &node) = 0;
|
||||
virtual void visit(VarDef &node) = 0;
|
||||
virtual void visit(AssignStmt &node) = 0;
|
||||
virtual void visit(FuncCallStmt &node) = 0;
|
||||
virtual void visit(BlockStmt &node) = 0;
|
||||
virtual void visit(EmptyStmt &node) = 0;
|
||||
virtual void visit(ExprStmt &node) = 0;
|
||||
virtual void visit(FuncParam &node) = 0;
|
||||
virtual void visit(FuncFParamList &node) = 0;
|
||||
virtual void visit(IfStmt &node) = 0;
|
||||
virtual void visit(WhileStmt &node) = 0;
|
||||
virtual void visit(BreakStmt &node) = 0;
|
||||
virtual void visit(ContinueStmt &node) = 0;
|
||||
virtual void visit(UnaryCondExpr &node) = 0;
|
||||
virtual void visit(BinaryCondExpr &node) = 0;
|
||||
virtual void visit(InitVal &node) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_SYNTAX_TREE_H_
|
@ -0,0 +1,43 @@
|
||||
#ifndef _SYSYF_SYNTAX_TREE_PRINTER_H_
|
||||
#define _SYSYF_SYNTAX_TREE_PRINTER_H_
|
||||
|
||||
#include "SyntaxTree.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace SyntaxTree
|
||||
{
|
||||
class SyntaxTreePrinter : public SyntaxTree::Visitor
|
||||
{
|
||||
public:
|
||||
virtual void visit(SyntaxTree::Assembly &node) override;
|
||||
virtual void visit(SyntaxTree::FuncDef &node) override;
|
||||
virtual void visit(SyntaxTree::BinaryExpr &node) override;
|
||||
virtual void visit(SyntaxTree::UnaryExpr &node) override;
|
||||
virtual void visit(SyntaxTree::LVal &node) override;
|
||||
virtual void visit(SyntaxTree::Literal &node) override;
|
||||
virtual void visit(SyntaxTree::ReturnStmt &node) override;
|
||||
virtual void visit(SyntaxTree::VarDef &node) override;
|
||||
virtual void visit(SyntaxTree::AssignStmt &node) override;
|
||||
virtual void visit(SyntaxTree::FuncCallStmt &node) override;
|
||||
virtual void visit(SyntaxTree::BlockStmt &node) override;
|
||||
virtual void visit(SyntaxTree::EmptyStmt &node) override;
|
||||
virtual void visit(SyntaxTree::ExprStmt &node) override;
|
||||
virtual void visit(SyntaxTree::FuncParam &node) override;
|
||||
virtual void visit(SyntaxTree::FuncFParamList &node) override;
|
||||
virtual void visit(SyntaxTree::BinaryCondExpr &node) override;
|
||||
virtual void visit(SyntaxTree::UnaryCondExpr &node) override;
|
||||
virtual void visit(SyntaxTree::IfStmt &node) override;
|
||||
virtual void visit(SyntaxTree::WhileStmt &node) override;
|
||||
virtual void visit(SyntaxTree::BreakStmt &node) override;
|
||||
virtual void visit(SyntaxTree::ContinueStmt &node) override;
|
||||
virtual void visit(SyntaxTree::InitVal &node) override;
|
||||
void print_indent();
|
||||
private:
|
||||
int indent = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_SYNTAX_TREE_PRINTER_H_
|
@ -0,0 +1,29 @@
|
||||
#ifndef _SYSYF_ERROR_REPORTER_H_
|
||||
#define _SYSYF_ERROR_REPORTER_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "SyntaxTree.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
class ErrorReporter
|
||||
{
|
||||
public:
|
||||
using Position = SyntaxTree::Position;
|
||||
explicit ErrorReporter(std::ostream &error_stream);
|
||||
|
||||
void error(Position pos, const std::string &msg);
|
||||
void warn(Position pos, const std::string &msg);
|
||||
|
||||
protected:
|
||||
virtual void report(Position pos, const std::string &msg, const std::string &prefix);
|
||||
|
||||
private:
|
||||
std::ostream &err;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // _SYSYF_ERROR_REPORTER_H_
|
@ -0,0 +1,225 @@
|
||||
// -*-C++-*-
|
||||
// FlexLexer.h -- define interfaces for lexical analyzer classes generated
|
||||
// by flex
|
||||
|
||||
// Copyright (c) 1993 The Regents of the University of California.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is derived from software contributed to Berkeley by
|
||||
// Kent Williams and Tom Epperly.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
|
||||
// Neither the name of the University nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE.
|
||||
|
||||
// This file defines FlexLexer, an abstract class which specifies the
|
||||
// external interface provided to flex C++ lexer objects, and yyFlexLexer,
|
||||
// which defines a particular lexer class.
|
||||
//
|
||||
// If you want to create multiple lexer classes, you use the -P flag
|
||||
// to rename each yyFlexLexer to some other xxFlexLexer. You then
|
||||
// include <FlexLexer.h> in your other sources once per lexer class:
|
||||
//
|
||||
// #undef yyFlexLexer
|
||||
// #define yyFlexLexer xxFlexLexer
|
||||
// #include <FlexLexer.h>
|
||||
//
|
||||
// #undef yyFlexLexer
|
||||
// #define yyFlexLexer zzFlexLexer
|
||||
// #include <FlexLexer.h>
|
||||
// ...
|
||||
|
||||
#ifndef __FLEX_LEXER_H
|
||||
// Never included before - need to define base class.
|
||||
#define __FLEX_LEXER_H
|
||||
|
||||
#include <iostream>
|
||||
# ifndef FLEX_STD
|
||||
# define FLEX_STD std::
|
||||
# endif
|
||||
|
||||
extern "C++" {
|
||||
|
||||
struct yy_buffer_state;
|
||||
typedef int yy_state_type;
|
||||
|
||||
class FlexLexer {
|
||||
public:
|
||||
virtual ~FlexLexer() { }
|
||||
|
||||
const char* YYText() const { return yytext; }
|
||||
int YYLeng() const { return yyleng; }
|
||||
|
||||
virtual void
|
||||
yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
|
||||
virtual struct yy_buffer_state*
|
||||
yy_create_buffer( FLEX_STD istream* s, int size ) = 0;
|
||||
virtual struct yy_buffer_state*
|
||||
yy_create_buffer( FLEX_STD istream& s, int size ) = 0;
|
||||
virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0;
|
||||
virtual void yyrestart( FLEX_STD istream* s ) = 0;
|
||||
virtual void yyrestart( FLEX_STD istream& s ) = 0;
|
||||
|
||||
virtual int yylex() = 0;
|
||||
|
||||
// Call yylex with new input/output sources.
|
||||
int yylex( FLEX_STD istream& new_in, FLEX_STD ostream& new_out )
|
||||
{
|
||||
switch_streams( new_in, new_out );
|
||||
return yylex();
|
||||
}
|
||||
|
||||
int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0)
|
||||
{
|
||||
switch_streams( new_in, new_out );
|
||||
return yylex();
|
||||
}
|
||||
|
||||
// Switch to new input/output streams. A nil stream pointer
|
||||
// indicates "keep the current one".
|
||||
virtual void switch_streams( FLEX_STD istream* new_in,
|
||||
FLEX_STD ostream* new_out ) = 0;
|
||||
virtual void switch_streams( FLEX_STD istream& new_in,
|
||||
FLEX_STD ostream& new_out ) = 0;
|
||||
|
||||
int lineno() const { return yylineno; }
|
||||
|
||||
int debug() const { return yy_flex_debug; }
|
||||
void set_debug( int flag ) { yy_flex_debug = flag; }
|
||||
|
||||
protected:
|
||||
char* yytext;
|
||||
int yyleng;
|
||||
int yylineno; // only maintained if you use %option yylineno
|
||||
int yy_flex_debug; // only has effect with -d or "%option debug"
|
||||
};
|
||||
|
||||
}
|
||||
#endif // FLEXLEXER_H
|
||||
|
||||
#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce)
|
||||
// Either this is the first time through (yyFlexLexerOnce not defined),
|
||||
// or this is a repeated include to define a different flavor of
|
||||
// yyFlexLexer, as discussed in the flex manual.
|
||||
#define yyFlexLexerOnce
|
||||
|
||||
extern "C++" {
|
||||
|
||||
class yyFlexLexer : public FlexLexer {
|
||||
public:
|
||||
// arg_yyin and arg_yyout default to the cin and cout, but we
|
||||
// only make that assignment when initializing in yylex().
|
||||
yyFlexLexer( FLEX_STD istream& arg_yyin, FLEX_STD ostream& arg_yyout );
|
||||
yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 );
|
||||
private:
|
||||
void ctor_common();
|
||||
|
||||
public:
|
||||
|
||||
virtual ~yyFlexLexer();
|
||||
|
||||
void yy_switch_to_buffer( struct yy_buffer_state* new_buffer );
|
||||
struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size );
|
||||
struct yy_buffer_state* yy_create_buffer( FLEX_STD istream& s, int size );
|
||||
void yy_delete_buffer( struct yy_buffer_state* b );
|
||||
void yyrestart( FLEX_STD istream* s );
|
||||
void yyrestart( FLEX_STD istream& s );
|
||||
|
||||
void yypush_buffer_state( struct yy_buffer_state* new_buffer );
|
||||
void yypop_buffer_state();
|
||||
|
||||
virtual int yylex();
|
||||
virtual void switch_streams( FLEX_STD istream& new_in, FLEX_STD ostream& new_out );
|
||||
virtual void switch_streams( FLEX_STD istream* new_in = 0, FLEX_STD ostream* new_out = 0 );
|
||||
virtual int yywrap();
|
||||
|
||||
protected:
|
||||
virtual int LexerInput( char* buf, int max_size );
|
||||
virtual void LexerOutput( const char* buf, int size );
|
||||
virtual void LexerError( const char* msg );
|
||||
|
||||
void yyunput( int c, char* buf_ptr );
|
||||
int yyinput();
|
||||
|
||||
void yy_load_buffer_state();
|
||||
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream& s );
|
||||
void yy_flush_buffer( struct yy_buffer_state* b );
|
||||
|
||||
int yy_start_stack_ptr;
|
||||
int yy_start_stack_depth;
|
||||
int* yy_start_stack;
|
||||
|
||||
void yy_push_state( int new_state );
|
||||
void yy_pop_state();
|
||||
int yy_top_state();
|
||||
|
||||
yy_state_type yy_get_previous_state();
|
||||
yy_state_type yy_try_NUL_trans( yy_state_type current_state );
|
||||
int yy_get_next_buffer();
|
||||
|
||||
FLEX_STD istream yyin; // input source for default LexerInput
|
||||
FLEX_STD ostream yyout; // output sink for default LexerOutput
|
||||
|
||||
// yy_hold_char holds the character lost when yytext is formed.
|
||||
char yy_hold_char;
|
||||
|
||||
// Number of characters read into yy_ch_buf.
|
||||
int yy_n_chars;
|
||||
|
||||
// Points to current character in buffer.
|
||||
char* yy_c_buf_p;
|
||||
|
||||
int yy_init; // whether we need to initialize
|
||||
int yy_start; // start state number
|
||||
|
||||
// Flag which is used to allow yywrap()'s to do buffer switches
|
||||
// instead of setting up a fresh yyin. A bit of a hack ...
|
||||
int yy_did_buffer_switch_on_eof;
|
||||
|
||||
|
||||
size_t yy_buffer_stack_top; /**< index of top of stack. */
|
||||
size_t yy_buffer_stack_max; /**< capacity of stack. */
|
||||
struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */
|
||||
void yyensure_buffer_stack(void);
|
||||
|
||||
// The following are not always needed, but may be depending
|
||||
// on use of certain flex features (like REJECT or yymore()).
|
||||
|
||||
yy_state_type yy_last_accepting_state;
|
||||
char* yy_last_accepting_cpos;
|
||||
|
||||
yy_state_type* yy_state_buf;
|
||||
yy_state_type* yy_state_ptr;
|
||||
|
||||
char* yy_full_match;
|
||||
int* yy_full_state;
|
||||
int yy_full_lp;
|
||||
|
||||
int yy_lp;
|
||||
int yy_looking_for_trail_begin;
|
||||
|
||||
int yy_more_flag;
|
||||
int yy_more_len;
|
||||
int yy_more_offset;
|
||||
int yy_prev_more_offset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // yyFlexLexer || ! yyFlexLexerOnce
|
||||
|
@ -0,0 +1,50 @@
|
||||
#ifndef _SYSYF_DRIVER_H_
|
||||
#define _SYSYF_DRIVER_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// Generated by bison:
|
||||
#include "SysYFParser.h"
|
||||
|
||||
#include "SysYFFlexLexer.h"
|
||||
|
||||
// Conducting the whole scanning and parsing of SysYF.
|
||||
class SysYFDriver
|
||||
{
|
||||
public:
|
||||
SysYFDriver();
|
||||
virtual ~SysYFDriver();
|
||||
|
||||
std::map<std::string, int> variables;
|
||||
|
||||
int result;
|
||||
|
||||
// SysYF lexer
|
||||
SysYFFlexLexer lexer;
|
||||
|
||||
std::ifstream instream;
|
||||
|
||||
// Handling the SysYF scanner.
|
||||
void scan_begin();
|
||||
void scan_end();
|
||||
bool trace_scanning;
|
||||
|
||||
// Run the parser on file F.
|
||||
// Return 0 on success.
|
||||
SysYF::Ptr<SysYF::SyntaxTree::Node> parse(const std::string& f);
|
||||
// The name of the file being parsed.
|
||||
// Used later to pass the file name to the location tracker.
|
||||
std::string file;
|
||||
// Whether parser traces should be generated.
|
||||
bool trace_parsing;
|
||||
|
||||
// Error handling.
|
||||
void error(const yy::location& l, const std::string& m);
|
||||
void error(const std::string& m);
|
||||
|
||||
SysYF::Ptr<SysYF::SyntaxTree::Node> root = nullptr;
|
||||
};
|
||||
|
||||
#endif // _SYSYF_DRIVER_H_
|
@ -0,0 +1,37 @@
|
||||
#ifndef _SYSYF_FLEX_LEXER_H_
|
||||
#define _SYSYF_FLEX_LEXER_H_
|
||||
|
||||
#ifndef YY_DECL
|
||||
#define YY_DECL \
|
||||
yy::SysYFParser::symbol_type SysYFFlexLexer::yylex(SysYFDriver& driver)
|
||||
#endif
|
||||
|
||||
// We need this for yyFlexLexer. If we don't #undef yyFlexLexer, the
|
||||
// preprocessor chokes on the line `#define yyFlexLexer yyFlexLexer`
|
||||
// in `FlexLexer.h`:
|
||||
#undef yyFlexLexer
|
||||
#include <FlexLexer.h>
|
||||
|
||||
// We need this for the yy::SysYFParser::symbol_type:
|
||||
#include "SysYFParser.h"
|
||||
|
||||
// We need this for the yy::location type:
|
||||
#include "location.hh"
|
||||
|
||||
class SysYFFlexLexer : public yyFlexLexer {
|
||||
public:
|
||||
// Use the superclass's constructor:
|
||||
using yyFlexLexer::yyFlexLexer;
|
||||
|
||||
// Provide the interface to `yylex`; `flex` will emit the
|
||||
// definition into `SysYFScanner.cpp`:
|
||||
yy::SysYFParser::symbol_type yylex(SysYFDriver& driver);
|
||||
|
||||
// This seems like a reasonable place to put the location object
|
||||
// rather than it being static (in the sense of having internal
|
||||
// linkage at translation unit scope, not in the sense of being a
|
||||
// class variable):
|
||||
yy::location loc;
|
||||
};
|
||||
|
||||
#endif // _SYSYF_FLEX_LEXER_H_
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,304 @@
|
||||
// A Bison parser, made by GNU Bison 3.8.2.
|
||||
|
||||
// Locations for Bison parsers in C++
|
||||
|
||||
// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// As a special exception, you may create a larger work that contains
|
||||
// part or all of the Bison parser skeleton and distribute that work
|
||||
// under terms of your choice, so long as that work isn't itself a
|
||||
// parser generator using the skeleton or a modified version thereof
|
||||
// as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
// the parser skeleton itself, you may (at your option) remove this
|
||||
// special exception, which will cause the skeleton and the resulting
|
||||
// Bison output files to be licensed under the GNU General Public
|
||||
// License without this special exception.
|
||||
|
||||
// This special exception was added by the Free Software Foundation in
|
||||
// version 2.2 of Bison.
|
||||
|
||||
/**
|
||||
** \file ./location.hh
|
||||
** Define the yy::location class.
|
||||
*/
|
||||
|
||||
#ifndef YY_YY_HOME_CJB_COMPILER_EDUCODER_EDUCODER_2021FALL_COMPILER_IR_LAB_SYSYF_TA_BUILD_LOCATION_HH_INCLUDED
|
||||
# define YY_YY_HOME_CJB_COMPILER_EDUCODER_EDUCODER_2021FALL_COMPILER_IR_LAB_SYSYF_TA_BUILD_LOCATION_HH_INCLUDED
|
||||
|
||||
# include <iostream>
|
||||
# include <string>
|
||||
|
||||
# ifndef YY_NULLPTR
|
||||
# if defined __cplusplus
|
||||
# if 201103L <= __cplusplus
|
||||
# define YY_NULLPTR nullptr
|
||||
# else
|
||||
# define YY_NULLPTR 0
|
||||
# endif
|
||||
# else
|
||||
# define YY_NULLPTR ((void*)0)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
namespace yy {
|
||||
#line 58 "./location.hh"
|
||||
|
||||
/// A point in a source file.
|
||||
class position
|
||||
{
|
||||
public:
|
||||
/// Type for file name.
|
||||
typedef const std::string filename_type;
|
||||
/// Type for line and column numbers.
|
||||
typedef int counter_type;
|
||||
|
||||
/// Construct a position.
|
||||
explicit position (filename_type* f = YY_NULLPTR,
|
||||
counter_type l = 1,
|
||||
counter_type c = 1)
|
||||
: filename (f)
|
||||
, line (l)
|
||||
, column (c)
|
||||
{}
|
||||
|
||||
|
||||
/// Initialization.
|
||||
void initialize (filename_type* fn = YY_NULLPTR,
|
||||
counter_type l = 1,
|
||||
counter_type c = 1)
|
||||
{
|
||||
filename = fn;
|
||||
line = l;
|
||||
column = c;
|
||||
}
|
||||
|
||||
/** \name Line and Column related manipulators
|
||||
** \{ */
|
||||
/// (line related) Advance to the COUNT next lines.
|
||||
void lines (counter_type count = 1)
|
||||
{
|
||||
if (count)
|
||||
{
|
||||
column = 1;
|
||||
line = add_ (line, count, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// (column related) Advance to the COUNT next columns.
|
||||
void columns (counter_type count = 1)
|
||||
{
|
||||
column = add_ (column, count, 1);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/// File name to which this position refers.
|
||||
filename_type* filename;
|
||||
/// Current line number.
|
||||
counter_type line;
|
||||
/// Current column number.
|
||||
counter_type column;
|
||||
|
||||
private:
|
||||
/// Compute max (min, lhs+rhs).
|
||||
static counter_type add_ (counter_type lhs, counter_type rhs, counter_type min)
|
||||
{
|
||||
return lhs + rhs < min ? min : lhs + rhs;
|
||||
}
|
||||
};
|
||||
|
||||
/// Add \a width columns, in place.
|
||||
inline position&
|
||||
operator+= (position& res, position::counter_type width)
|
||||
{
|
||||
res.columns (width);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Add \a width columns.
|
||||
inline position
|
||||
operator+ (position res, position::counter_type width)
|
||||
{
|
||||
return res += width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns, in place.
|
||||
inline position&
|
||||
operator-= (position& res, position::counter_type width)
|
||||
{
|
||||
return res += -width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns.
|
||||
inline position
|
||||
operator- (position res, position::counter_type width)
|
||||
{
|
||||
return res -= width;
|
||||
}
|
||||
|
||||
/** \brief Intercept output stream redirection.
|
||||
** \param ostr the destination output stream
|
||||
** \param pos a reference to the position to redirect
|
||||
*/
|
||||
template <typename YYChar>
|
||||
std::basic_ostream<YYChar>&
|
||||
operator<< (std::basic_ostream<YYChar>& ostr, const position& pos)
|
||||
{
|
||||
if (pos.filename)
|
||||
ostr << *pos.filename << ':';
|
||||
return ostr << pos.line << '.' << pos.column;
|
||||
}
|
||||
|
||||
/// Two points in a source file.
|
||||
class location
|
||||
{
|
||||
public:
|
||||
/// Type for file name.
|
||||
typedef position::filename_type filename_type;
|
||||
/// Type for line and column numbers.
|
||||
typedef position::counter_type counter_type;
|
||||
|
||||
/// Construct a location from \a b to \a e.
|
||||
location (const position& b, const position& e)
|
||||
: begin (b)
|
||||
, end (e)
|
||||
{}
|
||||
|
||||
/// Construct a 0-width location in \a p.
|
||||
explicit location (const position& p = position ())
|
||||
: begin (p)
|
||||
, end (p)
|
||||
{}
|
||||
|
||||
/// Construct a 0-width location in \a f, \a l, \a c.
|
||||
explicit location (filename_type* f,
|
||||
counter_type l = 1,
|
||||
counter_type c = 1)
|
||||
: begin (f, l, c)
|
||||
, end (f, l, c)
|
||||
{}
|
||||
|
||||
|
||||
/// Initialization.
|
||||
void initialize (filename_type* f = YY_NULLPTR,
|
||||
counter_type l = 1,
|
||||
counter_type c = 1)
|
||||
{
|
||||
begin.initialize (f, l, c);
|
||||
end = begin;
|
||||
}
|
||||
|
||||
/** \name Line and Column related manipulators
|
||||
** \{ */
|
||||
public:
|
||||
/// Reset initial location to final location.
|
||||
void step ()
|
||||
{
|
||||
begin = end;
|
||||
}
|
||||
|
||||
/// Extend the current location to the COUNT next columns.
|
||||
void columns (counter_type count = 1)
|
||||
{
|
||||
end += count;
|
||||
}
|
||||
|
||||
/// Extend the current location to the COUNT next lines.
|
||||
void lines (counter_type count = 1)
|
||||
{
|
||||
end.lines (count);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
|
||||
public:
|
||||
/// Beginning of the located region.
|
||||
position begin;
|
||||
/// End of the located region.
|
||||
position end;
|
||||
};
|
||||
|
||||
/// Join two locations, in place.
|
||||
inline location&
|
||||
operator+= (location& res, const location& end)
|
||||
{
|
||||
res.end = end.end;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Join two locations.
|
||||
inline location
|
||||
operator+ (location res, const location& end)
|
||||
{
|
||||
return res += end;
|
||||
}
|
||||
|
||||
/// Add \a width columns to the end position, in place.
|
||||
inline location&
|
||||
operator+= (location& res, location::counter_type width)
|
||||
{
|
||||
res.columns (width);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Add \a width columns to the end position.
|
||||
inline location
|
||||
operator+ (location res, location::counter_type width)
|
||||
{
|
||||
return res += width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns to the end position, in place.
|
||||
inline location&
|
||||
operator-= (location& res, location::counter_type width)
|
||||
{
|
||||
return res += -width;
|
||||
}
|
||||
|
||||
/// Subtract \a width columns to the end position.
|
||||
inline location
|
||||
operator- (location res, location::counter_type width)
|
||||
{
|
||||
return res -= width;
|
||||
}
|
||||
|
||||
/** \brief Intercept output stream redirection.
|
||||
** \param ostr the destination output stream
|
||||
** \param loc a reference to the location to redirect
|
||||
**
|
||||
** Avoid duplicate information.
|
||||
*/
|
||||
template <typename YYChar>
|
||||
std::basic_ostream<YYChar>&
|
||||
operator<< (std::basic_ostream<YYChar>& ostr, const location& loc)
|
||||
{
|
||||
location::counter_type end_col
|
||||
= 0 < loc.end.column ? loc.end.column - 1 : 0;
|
||||
ostr << loc.begin;
|
||||
if (loc.end.filename
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *loc.end.filename))
|
||||
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
|
||||
else if (loc.begin.line < loc.end.line)
|
||||
ostr << '-' << loc.end.line << '.' << end_col;
|
||||
else if (loc.begin.column < end_col)
|
||||
ostr << '-' << end_col;
|
||||
return ostr;
|
||||
}
|
||||
|
||||
} // yy
|
||||
#line 303 "./location.hh"
|
||||
|
||||
#endif // !YY_YY_HOME_CJB_COMPILER_EDUCODER_EDUCODER_2021FALL_COMPILER_IR_LAB_SYSYF_TA_BUILD_LOCATION_HH_INCLUDED
|
@ -0,0 +1,11 @@
|
||||
// A Bison parser, made by GNU Bison 3.8.2.
|
||||
|
||||
// Starting with Bison 3.2, this file is useless: the structure it
|
||||
// used to define is now defined in "location.hh".
|
||||
//
|
||||
// To get rid of this file:
|
||||
// 1. add '%require "3.2"' (or newer) to your grammar file
|
||||
// 2. remove references to this file from your build system
|
||||
// 3. if you used to include it, include "location.hh" instead.
|
||||
|
||||
#include "location.hh"
|
@ -0,0 +1,8 @@
|
||||
// A Bison parser, made by GNU Bison 3.8.2.
|
||||
|
||||
// Starting with Bison 3.2, this file is useless: the structure it
|
||||
// used to define is now defined with the parser itself.
|
||||
//
|
||||
// To get rid of this file:
|
||||
// 1. add '%require "3.2"' (or newer) to your grammar file
|
||||
// 2. remove references to this file from your build system.
|
@ -0,0 +1,86 @@
|
||||
#ifndef _SYSYF_BASICBLOCK_H_
|
||||
#define _SYSYF_BASICBLOCK_H_
|
||||
|
||||
#include "Value.h"
|
||||
#include "Instruction.h"
|
||||
#include "Module.h"
|
||||
#include "Function.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class Function;
|
||||
class Instruction;
|
||||
class Module;
|
||||
|
||||
class BasicBlock : public Value
|
||||
{
|
||||
public:
|
||||
static Ptr<BasicBlock> create(Ptr<Module> m, const std::string &name ,
|
||||
Ptr<Function> parent ) {
|
||||
auto prefix = name.empty() ? "" : "label_";
|
||||
RET_AFTER_INIT(BasicBlock, m, prefix + name, parent);
|
||||
}
|
||||
|
||||
// return parent, or null if none.
|
||||
Ptr<Function> get_parent() { return parent_; }
|
||||
|
||||
Ptr<Module> get_module();
|
||||
|
||||
/****************api about cfg****************/
|
||||
|
||||
PtrList<BasicBlock> &get_pre_basic_blocks() { return pre_bbs_; }
|
||||
PtrList<BasicBlock> &get_succ_basic_blocks() { return succ_bbs_; }
|
||||
void add_pre_basic_block(Ptr<BasicBlock> bb) { pre_bbs_.push_back(bb); }
|
||||
void add_succ_basic_block(Ptr<BasicBlock> bb) { succ_bbs_.push_back(bb); }
|
||||
|
||||
void remove_pre_basic_block(Ptr<BasicBlock> bb) { pre_bbs_.remove(bb); }
|
||||
void remove_succ_basic_block(Ptr<BasicBlock> bb) { succ_bbs_.remove(bb); }
|
||||
|
||||
/****************api about cfg****************/
|
||||
|
||||
/// Returns the terminator instruction if the block is well formed or null
|
||||
/// if the block is not well formed.
|
||||
const Ptr<Instruction> get_terminator() const;
|
||||
Ptr<Instruction> get_terminator() {
|
||||
return const_pointer_cast<Instruction>(
|
||||
static_pointer_cast<const BasicBlock>(shared_from_this())->get_terminator());
|
||||
}
|
||||
|
||||
void add_instruction(Ptr<Instruction> instr);
|
||||
void add_instruction(PtrList<Instruction>::iterator instr_pos, Ptr<Instruction> instr);
|
||||
void add_instr_begin(Ptr<Instruction> instr);
|
||||
|
||||
PtrList<Instruction>::iterator find_instruction(Ptr<Instruction> instr);
|
||||
|
||||
void delete_instr(Ptr<Instruction> instr);
|
||||
|
||||
bool empty() { return instr_list_.empty(); }
|
||||
|
||||
int get_num_of_instr() { return instr_list_.size(); }
|
||||
PtrList<Instruction> &get_instructions() { return instr_list_; }
|
||||
|
||||
void erase_from_parent();
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
explicit BasicBlock(Ptr<Module> m, const std::string &name ,
|
||||
Ptr<Function> parent );
|
||||
void init(Ptr<Module> m, const std::string &name ,
|
||||
Ptr<Function> parent );
|
||||
PtrList<BasicBlock> pre_bbs_;
|
||||
PtrList<BasicBlock> succ_bbs_;
|
||||
PtrList<Instruction> instr_list_;
|
||||
Ptr<Function> parent_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_BASICBLOCK_H_
|
@ -0,0 +1,90 @@
|
||||
#ifndef _SYSYF_CONSTANT_H_
|
||||
#define _SYSYF_CONSTANT_H_
|
||||
#include "User.h"
|
||||
#include "Value.h"
|
||||
#include "Type.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class Constant : public User
|
||||
{
|
||||
protected:
|
||||
explicit Constant(Ptr<Type> ty, const std::string &name = "", unsigned num_ops = 0)
|
||||
: User(ty, name, num_ops) {}
|
||||
void init(Ptr<Type> ty, const std::string &name = "", unsigned num_ops = 0) {}
|
||||
// int value;
|
||||
public:
|
||||
~Constant() = default;
|
||||
};
|
||||
|
||||
class ConstantInt : public Constant
|
||||
{
|
||||
private:
|
||||
int value_;
|
||||
explicit ConstantInt(Ptr<Type> ty, int val)
|
||||
: Constant(ty,"",0),value_(val) {}
|
||||
void init(Ptr<Type> ty, int val);
|
||||
|
||||
public:
|
||||
|
||||
static int get_value(Ptr<ConstantInt> const_val) { return const_val->value_; }
|
||||
int get_value() { return value_; }
|
||||
static Ptr<ConstantInt> create(int val, Ptr<Module> m);
|
||||
static Ptr<ConstantInt> create(bool val, Ptr<Module> m);
|
||||
virtual std::string print() override;
|
||||
};
|
||||
|
||||
class ConstantFloat : public Constant
|
||||
{
|
||||
private:
|
||||
float value_;
|
||||
explicit ConstantFloat(Ptr<Type> ty,float val)
|
||||
: Constant(ty,"",0),value_(val) {}
|
||||
void init(Ptr<Type> ty, float val);
|
||||
|
||||
public:
|
||||
|
||||
static float get_value(Ptr<ConstantFloat> const_val) { return const_val->value_; }
|
||||
float get_value() { return value_; }
|
||||
static Ptr<ConstantFloat> create(float val, Ptr<Module> m);
|
||||
virtual std::string print() override;
|
||||
};
|
||||
|
||||
class ConstantArray : public Constant
|
||||
{
|
||||
private:
|
||||
PtrVec<Constant> const_array;
|
||||
explicit ConstantArray(Ptr<ArrayType> ty, const PtrVec<Constant> &val);
|
||||
void init(Ptr<ArrayType> ty, const PtrVec<Constant> &val);
|
||||
|
||||
public:
|
||||
|
||||
~ConstantArray() = default;
|
||||
|
||||
Ptr<Constant> get_element_value(int index);
|
||||
|
||||
unsigned get_size_of_array() { return const_array.size(); }
|
||||
|
||||
static Ptr<ConstantArray> create(Ptr<ArrayType> ty, const PtrVec<Constant> &val);
|
||||
|
||||
virtual std::string print() override;
|
||||
};
|
||||
|
||||
class ConstantZero : public Constant
|
||||
{
|
||||
private:
|
||||
explicit ConstantZero(Ptr<Type> ty)
|
||||
: Constant(ty,"",0) {}
|
||||
void init(Ptr<Type> ty);
|
||||
|
||||
public:
|
||||
static Ptr<ConstantZero> create(Ptr<Type> ty, Ptr<Module> m);
|
||||
virtual std::string print() override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //_SYSYF_CONSTANT_H_
|
@ -0,0 +1,110 @@
|
||||
#ifndef _SYSYF_FUNCTION_H_
|
||||
#define _SYSYF_FUNCTION_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#ifdef DEBUG
|
||||
#include <cassert>
|
||||
#endif
|
||||
#include <set>
|
||||
|
||||
#include "User.h"
|
||||
#include "Module.h"
|
||||
#include "BasicBlock.h"
|
||||
#include "Type.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class Module;
|
||||
class Argument;
|
||||
class BasicBlock;
|
||||
class Type;
|
||||
class FunctionType;
|
||||
|
||||
class Function : public Value
|
||||
{
|
||||
public:
|
||||
~Function() = default;
|
||||
static Ptr<Function> create(Ptr<FunctionType> ty, const std::string &name, Ptr<Module> parent);
|
||||
|
||||
Ptr<FunctionType> get_function_type() const;
|
||||
|
||||
Ptr<Type> get_return_type() const;
|
||||
|
||||
void add_basic_block(Ptr<BasicBlock> bb);
|
||||
|
||||
unsigned get_num_of_args() const;
|
||||
unsigned get_num_basic_blocks() const;
|
||||
|
||||
Ptr<Module> get_parent() const;
|
||||
|
||||
PtrList<Argument>::iterator arg_begin() { return arguments_.begin(); }
|
||||
PtrList<Argument>::iterator arg_end() { return arguments_.end(); }
|
||||
|
||||
void remove(Ptr<BasicBlock> bb);
|
||||
Ptr<BasicBlock> get_entry_block() { return *basic_blocks_.begin(); }
|
||||
|
||||
PtrList<BasicBlock> &get_basic_blocks() { return basic_blocks_; }
|
||||
PtrList<Argument> &get_args() { return arguments_; }
|
||||
std::vector<PtrSet<Value>> &get_vreg_set(){ return vreg_set_;}
|
||||
|
||||
bool is_declaration() { return basic_blocks_.empty(); }
|
||||
void set_unused_reg_num(std::set<int>& set){unused_reg_num_ = set;}
|
||||
std::set<int>& get_unused_reg_num(){return unused_reg_num_;}
|
||||
|
||||
void set_instr_name();
|
||||
std::string print();
|
||||
|
||||
private:
|
||||
explicit Function(Ptr<FunctionType> ty, const std::string &name, Ptr<Module> parent);
|
||||
void init(Ptr<FunctionType> ty, const std::string &name, Ptr<Module> parent);
|
||||
void build_args();
|
||||
|
||||
private:
|
||||
PtrList<BasicBlock> basic_blocks_; // basic blocks
|
||||
PtrList<Argument> arguments_; // arguments
|
||||
std::vector<PtrSet<Value>> vreg_set_;
|
||||
Ptr<Module> parent_;
|
||||
std::set<int> unused_reg_num_;
|
||||
unsigned seq_cnt_;
|
||||
// unsigned num_args_;
|
||||
// We don't need this, all value inside function should be unnamed
|
||||
// std::map<std::string, Ptr<Value>> sym_table_; // Symbol table of args/instructions
|
||||
};
|
||||
|
||||
// Argument of Function, does not contain actual value
|
||||
class Argument : public Value
|
||||
{
|
||||
public:
|
||||
static Ptr<Argument> create(Ptr<Type> ty, const std::string &name = "", Ptr<Function> f = nullptr,
|
||||
unsigned arg_no = 0);
|
||||
~Argument() = default;
|
||||
|
||||
inline const Ptr<Function> get_parent() const { return parent_; }
|
||||
inline Ptr<Function> get_parent() { return parent_; }
|
||||
|
||||
/// For example in "void foo(int a, float b)" a is 0 and b is 1.
|
||||
unsigned get_arg_no() const {
|
||||
#ifdef DEBUG
|
||||
assert(parent_ && "can't get number of unparented arg");
|
||||
#endif
|
||||
return arg_no_;
|
||||
}
|
||||
|
||||
virtual std::string print() override ;
|
||||
private:
|
||||
// Argument constructor.
|
||||
explicit Argument(Ptr<Type> ty, const std::string &name = "", Ptr<Function> f = nullptr,
|
||||
unsigned arg_no = 0)
|
||||
: Value(ty, name), parent_(f), arg_no_(arg_no) {}
|
||||
Ptr<Function> parent_;
|
||||
unsigned arg_no_; // argument No.
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif // _SYSYF_FUNCTION_H_
|
@ -0,0 +1,31 @@
|
||||
#ifndef _SYSYF_GLOBALVARIABLE_H_
|
||||
#define _SYSYF_GLOBALVARIABLE_H_
|
||||
|
||||
#include "Module.h"
|
||||
#include "User.h"
|
||||
#include "Constant.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class GlobalVariable : public User
|
||||
{
|
||||
private:
|
||||
bool is_const_ ;
|
||||
Ptr<Constant> init_val_;
|
||||
explicit GlobalVariable(std::string name, Ptr<Module> m, Ptr<Type> ty, bool is_const, Ptr<Constant> init_val = nullptr);
|
||||
void init(std::string name, Ptr<Module> m, Ptr<Type> ty, bool is_const, Ptr<Constant> init_val = nullptr);
|
||||
|
||||
public:
|
||||
static Ptr<GlobalVariable> create(std::string name, Ptr<Module> m, Ptr<Type> ty, bool is_const, Ptr<Constant> init_val);
|
||||
|
||||
Ptr<Constant> get_init() { return init_val_; }
|
||||
bool is_const() { return is_const_; }
|
||||
std::string print();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //_SYSYF_GLOBALVARIABLE_H_
|
@ -0,0 +1,25 @@
|
||||
#ifndef _SYSYF_IPRINTER_H_
|
||||
#define _SYSYF_IPRINTER_H_
|
||||
|
||||
#include "Value.h"
|
||||
#include "Module.h"
|
||||
#include "Function.h"
|
||||
#include "GlobalVariable.h"
|
||||
#include "Constant.h"
|
||||
#include "BasicBlock.h"
|
||||
#include "Instruction.h"
|
||||
#include "User.h"
|
||||
#include "Type.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
std::string print_as_op(Ptr<Value> v, bool print_ty );
|
||||
std::string print_cmp_type(CmpInst::CmpOp op);
|
||||
std::string print_fcmp_type(FCmpInst::CmpOp op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,84 @@
|
||||
#ifndef _SYSYF_IRSTMTBUILDER_H_
|
||||
#define _SYSYF_IRSTMTBUILDER_H_
|
||||
|
||||
#include "BasicBlock.h"
|
||||
#include "Instruction.h"
|
||||
#include "Value.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class IRStmtBuilder {
|
||||
private:
|
||||
Ptr<BasicBlock> BB_;
|
||||
Ptr<Module> m_;
|
||||
explicit IRStmtBuilder(Ptr<BasicBlock> bb, Ptr<Module> m) : BB_(bb), m_(m) {};
|
||||
void init(Ptr<BasicBlock> bb, Ptr<Module> m) {}
|
||||
public:
|
||||
static Ptr<IRStmtBuilder> create(Ptr<BasicBlock> bb, Ptr<Module> m) { RET_AFTER_INIT(IRStmtBuilder, bb, m); }
|
||||
~IRStmtBuilder() = default;
|
||||
Ptr<Module> get_module(){return m_;}
|
||||
Ptr<BasicBlock> get_insert_block() { return this->BB_; }
|
||||
void set_insert_point(Ptr<BasicBlock> bb) { this->BB_ = bb; } //在某个基本块中插入指令
|
||||
Ptr<BinaryInst> create_iadd( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_add( lhs, rhs, this->BB_, m_);} //创建加法指令(以及其他算术指令)
|
||||
Ptr<BinaryInst> create_isub( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_sub( lhs, rhs, this->BB_, m_);}
|
||||
Ptr<BinaryInst> create_imul( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_mul( lhs, rhs, this->BB_, m_);}
|
||||
Ptr<BinaryInst> create_isdiv( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_sdiv( lhs, rhs, this->BB_, m_);}
|
||||
Ptr<BinaryInst> create_isrem( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_srem( lhs, rhs, this->BB_, m_);}
|
||||
|
||||
Ptr<CmpInst> create_icmp_eq( Ptr<Value> lhs, Ptr<Value> rhs){ return CmpInst::create_cmp(CmpInst::EQ, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<CmpInst> create_icmp_ne( Ptr<Value> lhs, Ptr<Value> rhs){ return CmpInst::create_cmp(CmpInst::NE, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<CmpInst> create_icmp_gt( Ptr<Value> lhs, Ptr<Value> rhs){ return CmpInst::create_cmp(CmpInst::GT, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<CmpInst> create_icmp_ge( Ptr<Value> lhs, Ptr<Value> rhs){ return CmpInst::create_cmp(CmpInst::GE, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<CmpInst> create_icmp_lt( Ptr<Value> lhs, Ptr<Value> rhs){ return CmpInst::create_cmp(CmpInst::LT, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<CmpInst> create_icmp_le( Ptr<Value> lhs, Ptr<Value> rhs){ return CmpInst::create_cmp(CmpInst::LE, lhs, rhs, this->BB_, m_); }
|
||||
|
||||
Ptr<BinaryInst> create_fadd( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_fadd( lhs, rhs, this->BB_, m_);}
|
||||
Ptr<BinaryInst> create_fsub( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_fsub( lhs, rhs, this->BB_, m_);}
|
||||
Ptr<BinaryInst> create_fmul( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_fmul( lhs, rhs, this->BB_, m_);}
|
||||
Ptr<BinaryInst> create_fdiv( Ptr<Value> lhs, Ptr<Value> rhs){ return BinaryInst::create_fdiv( lhs, rhs, this->BB_, m_);}
|
||||
|
||||
Ptr<FCmpInst> create_fcmp_eq( Ptr<Value> lhs, Ptr<Value> rhs){ return FCmpInst::create_fcmp(FCmpInst::EQ, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<FCmpInst> create_fcmp_ne( Ptr<Value> lhs, Ptr<Value> rhs){ return FCmpInst::create_fcmp(FCmpInst::NE, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<FCmpInst> create_fcmp_gt( Ptr<Value> lhs, Ptr<Value> rhs){ return FCmpInst::create_fcmp(FCmpInst::GT, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<FCmpInst> create_fcmp_ge( Ptr<Value> lhs, Ptr<Value> rhs){ return FCmpInst::create_fcmp(FCmpInst::GE, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<FCmpInst> create_fcmp_lt( Ptr<Value> lhs, Ptr<Value> rhs){ return FCmpInst::create_fcmp(FCmpInst::LT, lhs, rhs, this->BB_, m_); }
|
||||
Ptr<FCmpInst> create_fcmp_le( Ptr<Value> lhs, Ptr<Value> rhs){ return FCmpInst::create_fcmp(FCmpInst::LE, lhs, rhs, this->BB_, m_); }
|
||||
|
||||
Ptr<CallInst> create_call(Ptr<Value> func, PtrVec<Value> args)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert( dynamic_pointer_cast<Function>(func) && "func must be Ptr<Function> type");
|
||||
#endif
|
||||
return CallInst::create(static_pointer_cast<Function>(func) ,args, this->BB_);
|
||||
}
|
||||
|
||||
Ptr<BranchInst> create_br(Ptr<BasicBlock> if_true){ return BranchInst::create_br(if_true, this->BB_); }
|
||||
Ptr<BranchInst> create_cond_br(Ptr<Value> cond, Ptr<BasicBlock> if_true, Ptr<BasicBlock> if_false){ return BranchInst::create_cond_br(cond, if_true, if_false,this->BB_); }
|
||||
|
||||
Ptr<ReturnInst> create_ret(Ptr<Value> val) { return ReturnInst::create_ret(val,this->BB_); }
|
||||
Ptr<ReturnInst> create_void_ret() { return ReturnInst::create_void_ret(this->BB_); }
|
||||
|
||||
Ptr<GetElementPtrInst> create_gep(Ptr<Value> ptr, PtrVec<Value> idxs) { return GetElementPtrInst::create_gep(ptr, idxs, this->BB_); }
|
||||
|
||||
Ptr<StoreInst> create_store(Ptr<Value> val, Ptr<Value> ptr) { return StoreInst::create_store(val, ptr, this->BB_ ); }
|
||||
Ptr<LoadInst> create_load(Ptr<Type> ty, Ptr<Value> ptr) { return LoadInst::create_load(ty, ptr, this->BB_); }
|
||||
Ptr<LoadInst> create_load(Ptr<Value> ptr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert( ptr->get_type()->is_pointer_type() && "ptr must be pointer type" );
|
||||
#endif
|
||||
return LoadInst::create_load(ptr->get_type()->get_pointer_element_type(), ptr, this->BB_);
|
||||
}
|
||||
|
||||
Ptr<AllocaInst> create_alloca(Ptr<Type> ty) { return AllocaInst::create_alloca(ty, this->BB_); }
|
||||
Ptr<ZextInst> create_zext(Ptr<Value> val, Ptr<Type> ty) { return ZextInst::create_zext(val, ty, this->BB_); }
|
||||
Ptr<FpToSiInst> create_fptosi(Ptr<Value> val, Ptr<Type> ty) { return FpToSiInst::create_fptosi(val, ty, this->BB_); }
|
||||
Ptr<SiToFpInst> create_sitofp(Ptr<Value> val, Ptr<Type> ty) { return SiToFpInst::create_sitofp(val, ty, this->BB_); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_IRSTMTBUILDER_H_
|
@ -0,0 +1,435 @@
|
||||
#ifndef _SYSYF_INSTRUCTION_H_
|
||||
#define _SYSYF_INSTRUCTION_H_
|
||||
|
||||
#include "User.h"
|
||||
#include "Type.h"
|
||||
#include "Constant.h"
|
||||
#include "BasicBlock.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class Instruction;
|
||||
|
||||
class Instruction : public User
|
||||
{
|
||||
public:
|
||||
enum OpID
|
||||
{
|
||||
// Terminator Instructions
|
||||
ret,
|
||||
br,
|
||||
// Standard binary operators
|
||||
add,
|
||||
sub,
|
||||
mul,
|
||||
sdiv,
|
||||
srem,
|
||||
// Float binaru opeartors
|
||||
fadd,
|
||||
fsub,
|
||||
fmul,
|
||||
fdiv,
|
||||
// Memory operators
|
||||
alloca,
|
||||
load,
|
||||
store,
|
||||
// Other operators
|
||||
cmp,
|
||||
fcmp,
|
||||
phi,
|
||||
call,
|
||||
getelementptr,
|
||||
// Zero extend
|
||||
zext,
|
||||
// type cast bewteen float and singed integer
|
||||
fptosi,
|
||||
sitofp,
|
||||
};
|
||||
inline const Ptr<BasicBlock> get_parent() const { return parent_; }
|
||||
inline Ptr<BasicBlock> get_parent() { return parent_; }
|
||||
void set_parent(Ptr<BasicBlock> parent) { this->parent_ = parent; }
|
||||
// Return the function this instruction belongs to.
|
||||
Ptr<Function> get_function();
|
||||
Ptr<Module> get_module();
|
||||
|
||||
OpID get_instr_type() { return op_id_; }
|
||||
std::string get_instr_op_name() {
|
||||
switch (op_id_)
|
||||
{
|
||||
case ret: return "ret"; break;
|
||||
case br: return "br"; break;
|
||||
case add: return "add"; break;
|
||||
case sub: return "sub"; break;
|
||||
case mul: return "mul"; break;
|
||||
case sdiv: return "sdiv"; break;
|
||||
case srem: return "srem"; break;
|
||||
case fadd: return "fadd"; break;
|
||||
case fsub: return "fsub"; break;
|
||||
case fmul: return "fmul"; break;
|
||||
case fdiv: return "fdiv"; break;
|
||||
case alloca: return "alloca"; break;
|
||||
case load: return "load"; break;
|
||||
case store: return "store"; break;
|
||||
case cmp: return "cmp"; break;
|
||||
case fcmp: return "fcmp"; break;
|
||||
case phi: return "phi"; break;
|
||||
case call: return "call"; break;
|
||||
case getelementptr: return "getelementptr"; break;
|
||||
case zext: return "zext"; break;
|
||||
case fptosi: return "fptosi"; break;
|
||||
case sitofp: return "sitofp"; break;
|
||||
|
||||
default: return ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool is_void() { return ((op_id_ == ret) || (op_id_ == br) || (op_id_ == store) || (op_id_ == call && this->get_type()->is_void_type())); }
|
||||
|
||||
bool is_phi() { return op_id_ == phi; }
|
||||
bool is_store() { return op_id_ == store; }
|
||||
bool is_alloca() { return op_id_ == alloca; }
|
||||
bool is_ret() { return op_id_ == ret; }
|
||||
bool is_load() { return op_id_ == load; }
|
||||
bool is_br() { return op_id_ == br; }
|
||||
|
||||
bool is_add() { return op_id_ == add; }
|
||||
bool is_sub() { return op_id_ == sub; }
|
||||
bool is_mul() { return op_id_ == mul; }
|
||||
bool is_div() { return op_id_ == sdiv; }
|
||||
bool is_rem() { return op_id_ == srem; }
|
||||
|
||||
bool is_fadd() { return op_id_ == fadd; }
|
||||
bool is_fsub() { return op_id_ == fsub; }
|
||||
bool is_fmul() { return op_id_ == fmul; }
|
||||
bool is_fdiv() { return op_id_ == fdiv; }
|
||||
|
||||
bool is_cmp() { return op_id_ == cmp; }
|
||||
bool is_fcmp() { return op_id_ == fcmp; }
|
||||
|
||||
bool is_call() { return op_id_ == call; }
|
||||
bool is_gep() { return op_id_ == getelementptr; }
|
||||
bool is_zext() { return op_id_ == zext; }
|
||||
bool is_fptosi() { return op_id_ == fptosi; }
|
||||
bool is_sitofp() { return op_id_ == sitofp; }
|
||||
|
||||
bool isBinary()
|
||||
{
|
||||
return (is_add() || is_sub() || is_mul() || is_div() || is_rem() ||
|
||||
is_fadd() || is_fsub() || is_fmul() || is_fdiv()) &&
|
||||
(get_num_operand() == 2);
|
||||
}
|
||||
|
||||
bool isTerminator() { return is_br() || is_ret(); }
|
||||
|
||||
void set_id(int id){id_ = id;}
|
||||
int get_id() const{return id_;}
|
||||
|
||||
private:
|
||||
OpID op_id_;
|
||||
int id_;
|
||||
unsigned num_ops_;
|
||||
Ptr<BasicBlock> parent_;
|
||||
// must be called after Instruction() in any derived class
|
||||
void insert_to_bb();
|
||||
|
||||
protected:
|
||||
// create instruction, but not insert to bb (insert to bb in method create in the derived class)
|
||||
// ty here is result type
|
||||
explicit Instruction(Ptr<Type> ty, OpID id, unsigned num_ops, Ptr<BasicBlock> parent = nullptr);
|
||||
void init(Ptr<Type> ty, OpID id, unsigned num_ops, Ptr<BasicBlock> parent = nullptr);
|
||||
};
|
||||
|
||||
class BinaryInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit BinaryInst(Ptr<Type> ty, OpID id, Ptr<Value> v1, Ptr<Value> v2,
|
||||
Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<BinaryInst> create_add(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_sub(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_mul(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_sdiv(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_srem(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_fadd(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_fsub(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_fmul(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
static Ptr<BinaryInst> create_fdiv(Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
void init(Ptr<Type> ty, OpID id, Ptr<Value> v1, Ptr<Value> v2, Ptr<BasicBlock> bb);
|
||||
void assertValid() {}
|
||||
};
|
||||
|
||||
class CmpInst : public Instruction
|
||||
{
|
||||
public:
|
||||
enum CmpOp
|
||||
{
|
||||
EQ, // ==
|
||||
NE, // !=
|
||||
GT, // >
|
||||
GE, // >=
|
||||
LT, // <
|
||||
LE // <=
|
||||
};
|
||||
|
||||
private:
|
||||
explicit CmpInst(Ptr<Type> ty, CmpOp op, Ptr<Value> lhs, Ptr<Value> rhs,
|
||||
Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<CmpInst> create_cmp(CmpOp op, Ptr<Value> lhs, Ptr<Value> rhs,
|
||||
Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
|
||||
CmpOp get_cmp_op() { return cmp_op_; }
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
CmpOp cmp_op_;
|
||||
void init(Ptr<Type> ty, CmpOp op, Ptr<Value> lhs, Ptr<Value> rhs, Ptr<BasicBlock> bb);
|
||||
void assertValid() {}
|
||||
};
|
||||
|
||||
class FCmpInst : public Instruction
|
||||
{
|
||||
public:
|
||||
enum CmpOp
|
||||
{
|
||||
EQ, // ==
|
||||
NE, // !=
|
||||
GT, // >
|
||||
GE, // >=
|
||||
LT, // <
|
||||
LE // <=
|
||||
};
|
||||
|
||||
private:
|
||||
explicit FCmpInst(Ptr<Type> ty, CmpOp op, Ptr<Value> lhs, Ptr<Value> rhs,
|
||||
Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Type> ty, CmpOp op, Ptr<Value> lhs, Ptr<Value> rhs, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<FCmpInst> create_fcmp(CmpOp op, Ptr<Value> lhs, Ptr<Value> rhs,
|
||||
Ptr<BasicBlock> bb, Ptr<Module> m);
|
||||
|
||||
CmpOp get_cmp_op() { return cmp_op_; }
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
CmpOp cmp_op_;
|
||||
|
||||
void assertValid() {}
|
||||
};
|
||||
|
||||
class CallInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit CallInst(Ptr<Function> func, PtrVec<Value> args, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Function> func, PtrVec<Value> args, Ptr<BasicBlock> bb);
|
||||
explicit CallInst(Ptr<Type> ret_ty, PtrVec<Value> args, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Type> ret_ty, PtrVec<Value> args, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<CallInst> create(Ptr<Function> func, PtrVec<Value> args, Ptr<BasicBlock> bb);
|
||||
Ptr<FunctionType> get_function_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
};
|
||||
|
||||
class BranchInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit BranchInst(Ptr<Value> cond, Ptr<BasicBlock> if_true, Ptr<BasicBlock> if_false,
|
||||
Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Value> cond, Ptr<BasicBlock> if_true, Ptr<BasicBlock> if_false,
|
||||
Ptr<BasicBlock> bb);
|
||||
explicit BranchInst(Ptr<Value> cond, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Value> cond, Ptr<BasicBlock> bb);
|
||||
explicit BranchInst(Ptr<BasicBlock> if_true, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<BasicBlock> if_true, Ptr<BasicBlock> bb);
|
||||
explicit BranchInst(Ptr<BasicBlock> bb);
|
||||
void init(Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<BranchInst> create_cond_br(Ptr<Value> cond, Ptr<BasicBlock> if_true, Ptr<BasicBlock> if_false,
|
||||
Ptr<BasicBlock> bb);
|
||||
static Ptr<BranchInst> create_br(Ptr<BasicBlock> if_true, Ptr<BasicBlock> bb);
|
||||
|
||||
bool is_cond_br() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
};
|
||||
|
||||
class ReturnInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit ReturnInst(Ptr<Value> val, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Value> val, Ptr<BasicBlock> bb);
|
||||
explicit ReturnInst(Ptr<BasicBlock> bb);
|
||||
void init(Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<ReturnInst> create_ret(Ptr<Value> val, Ptr<BasicBlock> bb);
|
||||
static Ptr<ReturnInst> create_void_ret(Ptr<BasicBlock> bb);
|
||||
bool is_void_ret() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
};
|
||||
|
||||
class GetElementPtrInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit GetElementPtrInst(Ptr<Value> ptr, PtrVec<Value> idxs, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Value> ptr, PtrVec<Value> idxs, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<Type> get_element_type(Ptr<Value> ptr, PtrVec<Value> idxs);
|
||||
static Ptr<GetElementPtrInst> create_gep(Ptr<Value> ptr, PtrVec<Value> idxs, Ptr<BasicBlock> bb);
|
||||
Ptr<Type> get_element_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
Ptr<Type> element_ty_;
|
||||
};
|
||||
|
||||
class StoreInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit StoreInst(Ptr<Value> val, Ptr<Value> ptr, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Value> val, Ptr<Value> ptr, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<StoreInst> create_store(Ptr<Value> val, Ptr<Value> ptr, Ptr<BasicBlock> bb);
|
||||
|
||||
Ptr<Value> get_rval() { return this->get_operand(0); }
|
||||
Ptr<Value> get_lval() { return this->get_operand(1); }
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
};
|
||||
|
||||
class LoadInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit LoadInst(Ptr<Type> ty, Ptr<Value> ptr, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Type> ty, Ptr<Value> ptr, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<LoadInst> create_load(Ptr<Type> ty, Ptr<Value> ptr, Ptr<BasicBlock> bb);
|
||||
Ptr<Value> get_lval() { return this->get_operand(0); }
|
||||
|
||||
Ptr<Type> get_load_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
};
|
||||
|
||||
class AllocaInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit AllocaInst(Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
void init(Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<AllocaInst> create_alloca(Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
Ptr<Type> get_alloca_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
Ptr<Type> alloca_ty_;
|
||||
};
|
||||
|
||||
class ZextInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit ZextInst(OpID op, Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
void init(OpID op, Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<ZextInst> create_zext(Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
Ptr<Type> get_dest_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
Ptr<Type> dest_ty_;
|
||||
};
|
||||
|
||||
class FpToSiInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit FpToSiInst(OpID op, Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
void init(OpID op, Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<FpToSiInst> create_fptosi(Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
Ptr<Type> get_dest_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
Ptr<Type> dest_ty_;
|
||||
};
|
||||
|
||||
class SiToFpInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit SiToFpInst(OpID op, Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
void init(OpID op, Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<SiToFpInst> create_sitofp(Ptr<Value> val, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
Ptr<Type> get_dest_type() const;
|
||||
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
Ptr<Type> dest_ty_;
|
||||
};
|
||||
|
||||
class PhiInst : public Instruction
|
||||
{
|
||||
private:
|
||||
explicit PhiInst(OpID op, PtrVec<Value> vals, PtrVec<BasicBlock> val_bbs, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
void init(OpID op, PtrVec<Value> vals, PtrVec<BasicBlock> val_bbs, Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
|
||||
public:
|
||||
static Ptr<PhiInst> create_phi(Ptr<Type> ty, Ptr<BasicBlock> bb);
|
||||
Ptr<Value> get_lval() { return l_val_; }
|
||||
void set_lval(Ptr<Value> l_val) { l_val_ = l_val; }
|
||||
void add_phi_pair_operand(Ptr<Value> val, Ptr<Value> pre_bb)
|
||||
{
|
||||
this->add_operand(val);
|
||||
this->add_operand(pre_bb);
|
||||
}
|
||||
virtual std::string print() override;
|
||||
|
||||
private:
|
||||
Ptr<Value> l_val_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_INSTRUCTION_H_
|
@ -0,0 +1,73 @@
|
||||
#ifndef _SYSYF_MODULE_H_
|
||||
#define _SYSYF_MODULE_H_
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "internal_types.h"
|
||||
#include "internal_macros.h"
|
||||
#include "Type.h"
|
||||
#include "GlobalVariable.h"
|
||||
#include "Value.h"
|
||||
#include "Function.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class GlobalVariable;
|
||||
class Module;
|
||||
|
||||
class Module : public std::enable_shared_from_this<Module>
|
||||
{
|
||||
public:
|
||||
static Ptr<Module> create(std::string name);
|
||||
~Module() = default;
|
||||
|
||||
Ptr<Type> get_void_type();
|
||||
Ptr<Type> get_label_type();
|
||||
Ptr<IntegerType> get_int1_type();
|
||||
Ptr<IntegerType> get_int32_type();
|
||||
Ptr<FloatType> get_float_type();
|
||||
Ptr<PointerType> get_int32_ptr_type();
|
||||
Ptr<PointerType> get_float_ptr_type();
|
||||
|
||||
Ptr<PointerType> get_pointer_type(Ptr<Type> contained);
|
||||
Ptr<ArrayType> get_array_type(Ptr<Type> contained, unsigned num_elements);
|
||||
|
||||
void add_function(Ptr<Function> f);
|
||||
PtrList<Function> &get_functions();
|
||||
void add_global_variable(Ptr<GlobalVariable> g);
|
||||
PtrList<GlobalVariable> &get_global_variable();
|
||||
std::string get_instr_op_name( Instruction::OpID instr ) { return instr_id2string_[instr]; }
|
||||
void set_print_name();
|
||||
void set_file_name(std::string name){source_file_name_ = name;}
|
||||
std::string get_file_name(){return source_file_name_;}
|
||||
virtual std::string print();
|
||||
private:
|
||||
explicit Module(std::string name);
|
||||
void init(std::string name);
|
||||
PtrList<GlobalVariable> global_list_; // The Global Variables in the module
|
||||
PtrList<Function> function_list_; // The Functions in the module
|
||||
std::map<std::string, Ptr<Value>> value_sym_; // Symbol table for values
|
||||
std::map<Instruction::OpID, std::string> instr_id2string_; // Instruction from opid to string
|
||||
|
||||
std::string module_name_; // Human readable identifier for the module
|
||||
std::string source_file_name_; // Original source file name for module, for test and debug
|
||||
|
||||
private:
|
||||
Ptr<IntegerType> int1_ty_;
|
||||
Ptr<IntegerType> int32_ty_;
|
||||
Ptr<FloatType> float32_ty_;
|
||||
Ptr<Type> label_ty_;
|
||||
Ptr<Type> void_ty_;
|
||||
|
||||
std::map<Ptr<Type> , Ptr<PointerType>> pointer_map_;
|
||||
std::map<std::pair<Ptr<Type> ,int>, Ptr<ArrayType> > array_map_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_MODULE_H_
|
@ -0,0 +1,162 @@
|
||||
#ifndef _SYSYF_TYPE_H_
|
||||
#define _SYSYF_TYPE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include "internal_types.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class Module;
|
||||
class IntegerType;
|
||||
class FloatType;
|
||||
class FunctionType;
|
||||
class ArrayType;
|
||||
class PointerType;
|
||||
class Type;
|
||||
|
||||
class Type : public std::enable_shared_from_this<Type>
|
||||
{
|
||||
public:
|
||||
enum TypeID {
|
||||
VoidTyID, // Void
|
||||
LabelTyID, // Labels, e.g., BasicBlock
|
||||
IntegerTyID, // Integers, include 32 bits and 1 bit
|
||||
FloatTyID, // Floats, only 32 bits
|
||||
FunctionTyID, // Functions
|
||||
ArrayTyID, // Arrays
|
||||
PointerTyID, // Pointer
|
||||
};
|
||||
|
||||
static Ptr<Type> create(TypeID tid, Ptr<Module> m);
|
||||
|
||||
~Type() = default;
|
||||
|
||||
TypeID get_type_id() const { return tid_; }
|
||||
|
||||
bool is_void_type() const { return get_type_id() == VoidTyID; }
|
||||
|
||||
bool is_label_type() const { return get_type_id() == LabelTyID; }
|
||||
|
||||
bool is_integer_type() const { return get_type_id() == IntegerTyID; }
|
||||
|
||||
bool is_float_type() const { return get_type_id() == FloatTyID; }
|
||||
|
||||
bool is_function_type() const { return get_type_id() == FunctionTyID; }
|
||||
|
||||
bool is_array_type() const { return get_type_id() == ArrayTyID; }
|
||||
|
||||
bool is_pointer_type() const { return get_type_id() == PointerTyID; }
|
||||
|
||||
static bool is_eq_type(Ptr<Type> ty1, Ptr<Type> ty2);
|
||||
|
||||
static Ptr<Type> get_void_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<Type> get_label_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<IntegerType> get_int1_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<IntegerType> get_int32_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<FloatType> get_float_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<PointerType> get_int32_ptr_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<PointerType> get_float_ptr_type(Ptr<Module> m);
|
||||
|
||||
static Ptr<PointerType> get_pointer_type(Ptr<Type> contained);
|
||||
|
||||
static Ptr<ArrayType> get_array_type(Ptr<Type> contained, unsigned num_elements);
|
||||
|
||||
Ptr<Type> get_pointer_element_type();
|
||||
|
||||
Ptr<Type> get_array_element_type();
|
||||
|
||||
int get_size();
|
||||
|
||||
Ptr<Module> get_module();
|
||||
|
||||
std::string print();
|
||||
|
||||
protected:
|
||||
explicit Type(TypeID tid, Ptr<Module> m);
|
||||
void init(TypeID tid, Ptr<Module> m) {}
|
||||
|
||||
private:
|
||||
TypeID tid_;
|
||||
Ptr<Module> m_;
|
||||
};
|
||||
|
||||
class IntegerType : public Type {
|
||||
public:
|
||||
static Ptr<IntegerType> create(unsigned num_bits, Ptr<Module> m );
|
||||
|
||||
unsigned get_num_bits();
|
||||
private:
|
||||
explicit IntegerType(unsigned num_bits ,Ptr<Module> m);
|
||||
void init(unsigned num_bits ,Ptr<Module> m) { Type::init(IntegerTyID, m); }
|
||||
unsigned num_bits_;
|
||||
};
|
||||
|
||||
class FloatType : public Type {
|
||||
public:
|
||||
static Ptr<FloatType> create(Ptr<Module> m);
|
||||
private:
|
||||
explicit FloatType(Ptr<Module> m);
|
||||
void init(Ptr<Module> m) { Type::init(FloatTyID, m); }
|
||||
};
|
||||
|
||||
class FunctionType : public Type {
|
||||
public:
|
||||
static Ptr<FunctionType> create(Ptr<Type> result, PtrVec<Type> params);
|
||||
static bool is_valid_return_type(Ptr<Type> ty);
|
||||
static bool is_valid_argument_type(Ptr<Type> ty);
|
||||
|
||||
unsigned get_num_of_args() const;
|
||||
|
||||
Ptr<Type> get_param_type(unsigned i) const;
|
||||
PtrVec<Type>::iterator param_begin() { return args_.begin(); }
|
||||
PtrVec<Type>::iterator param_end() { return args_.end(); }
|
||||
Ptr<Type> get_return_type() const;
|
||||
private:
|
||||
explicit FunctionType(Ptr<Type> result, PtrVec<Type> params);
|
||||
void init(Ptr<Type> result, PtrVec<Type> params) { Type::init(FunctionTyID, nullptr); }
|
||||
Ptr<Type> result_;
|
||||
PtrVec<Type> args_;
|
||||
};
|
||||
|
||||
class ArrayType : public Type {
|
||||
public:
|
||||
static bool is_valid_element_type(Ptr<Type> ty);
|
||||
|
||||
static Ptr<ArrayType> get(Ptr<Type> contained, unsigned num_elements);
|
||||
static Ptr<ArrayType> create(Ptr<Type> contained, unsigned num_elements);
|
||||
|
||||
Ptr<Type> get_element_type() const { return contained_; }
|
||||
unsigned get_num_of_elements() const { return num_elements_; }
|
||||
|
||||
private:
|
||||
explicit ArrayType(Ptr<Type> contained, unsigned num_elements);
|
||||
void init(Ptr<Type> contained, unsigned num_elements) { Type::init(ArrayTyID, nullptr); }
|
||||
Ptr<Type> contained_; // The element type of the array.
|
||||
unsigned num_elements_; // Number of elements in the array.
|
||||
};
|
||||
|
||||
class PointerType : public Type {
|
||||
public:
|
||||
Ptr<Type> get_element_type() const { return contained_; }
|
||||
static Ptr<PointerType> get(Ptr<Type> contained);
|
||||
static Ptr<PointerType> create(Ptr<Type> contained);
|
||||
|
||||
private:
|
||||
explicit PointerType(Ptr<Type> contained);
|
||||
void init(Ptr<Type> contained) { Type::init(PointerTyID, nullptr); }
|
||||
Ptr<Type> contained_; // The element type of the ptr.
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif // _SYSYF_TYPE_H_
|
@ -0,0 +1,41 @@
|
||||
#ifndef _SYSYF_USER_H_
|
||||
#define _SYSYF_USER_H_
|
||||
|
||||
#include "Value.h"
|
||||
#include <vector>
|
||||
// #include <memory>
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class User : public Value
|
||||
{
|
||||
public:
|
||||
~User() = default;
|
||||
|
||||
PtrVec<Value>& get_operands();
|
||||
|
||||
// start from 0
|
||||
Ptr<Value> get_operand(unsigned i) const;
|
||||
|
||||
// start from 0
|
||||
void set_operand(unsigned i, Ptr<Value> v);
|
||||
void add_operand(Ptr<Value> v);
|
||||
|
||||
unsigned get_num_operand() const;
|
||||
|
||||
void remove_use_of_ops();
|
||||
void remove_operands(int index1,int index2);
|
||||
|
||||
protected:
|
||||
explicit User(Ptr<Type> ty, const std::string &name = "", unsigned num_ops = 0);
|
||||
|
||||
private:
|
||||
PtrVec<Value> operands_; // operands of this value
|
||||
unsigned num_ops_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif // _SYSYF_USER_H_
|
@ -0,0 +1,63 @@
|
||||
#ifndef _SYSYF_VALUE_H_
|
||||
#define _SYSYF_VALUE_H_
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "internal_types.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
struct Use
|
||||
{
|
||||
Ptr<Value> val_;
|
||||
unsigned arg_no_; // the no. of operand, e.g., func(a, b), a is 0, b is 1
|
||||
Use(Ptr<Value> val, unsigned no) : val_(val), arg_no_(no) {}
|
||||
};
|
||||
|
||||
class Value : public std::enable_shared_from_this<Value>
|
||||
{
|
||||
public:
|
||||
~Value() = default;
|
||||
|
||||
Ptr<Type> get_type() const { return type_; }
|
||||
|
||||
std::list<Use> &get_use_list() { return use_list_; }
|
||||
|
||||
void add_use(Ptr<Value> val, unsigned arg_no = 0);
|
||||
|
||||
bool set_name(std::string name) {
|
||||
if (name_ == "")
|
||||
{
|
||||
name_=name;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::string get_name() const;
|
||||
|
||||
void replace_all_use_with(Ptr<Value> new_val);
|
||||
void remove_use(Ptr<Value> val);
|
||||
|
||||
virtual std::string print() = 0;
|
||||
|
||||
protected:
|
||||
explicit Value(Ptr<Type> ty, const std::string &name = "");
|
||||
|
||||
private:
|
||||
Ptr<Type> type_;
|
||||
std::list<Use> use_list_; // who use this value
|
||||
std::string name_; // should we put name field here ?
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif // _SYSYF_VALUE_H_
|
@ -0,0 +1,226 @@
|
||||
#ifndef _SYSYF_IR_BUILDER_H_
|
||||
#define _SYSYF_IR_BUILDER_H_
|
||||
#include "BasicBlock.h"
|
||||
#include "Constant.h"
|
||||
#include "Function.h"
|
||||
#include "IRStmtBuilder.h"
|
||||
#include "Module.h"
|
||||
#include "Type.h"
|
||||
#include <map>
|
||||
#include "SyntaxTree.h"
|
||||
|
||||
namespace SysYF
|
||||
{
|
||||
namespace IR
|
||||
{
|
||||
class Scope {
|
||||
public:
|
||||
// enter a new scope
|
||||
void enter() {
|
||||
name2var.push_back({});
|
||||
name2func.push_back({});
|
||||
}
|
||||
|
||||
// exit a scope
|
||||
void exit() {
|
||||
name2var.pop_back();
|
||||
name2func.pop_back();
|
||||
}
|
||||
|
||||
bool in_global() {
|
||||
return name2var.size() == 1;
|
||||
}
|
||||
|
||||
// push a name to scope
|
||||
// return true if successful
|
||||
// return false if this name already exits
|
||||
// but func name could be same with variable name
|
||||
bool push(std::string name, Ptr<Value> val) {
|
||||
bool result;
|
||||
if (dynamic_pointer_cast<Function>(val)){
|
||||
result = (name2func[name2func.size() - 1].insert({name, val})).second;
|
||||
}
|
||||
else{
|
||||
result = (name2var[name2var.size() - 1].insert({name, val})).second;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Ptr<Value> find(std::string name, bool isfunc) {
|
||||
if (isfunc){
|
||||
for (auto s = name2func.rbegin(); s!= name2func.rend();s++) {
|
||||
auto iter = s->find(name);
|
||||
if (iter != s->end()) {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
for (auto s = name2var.rbegin(); s!= name2var.rend();s++) {
|
||||
auto iter = s->find(name);
|
||||
if (iter != s->end()) {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<std::map<std::string, Ptr<Value> >> name2var;
|
||||
std::vector<std::map<std::string, Ptr<Value> >> name2func;
|
||||
};
|
||||
|
||||
class IRBuilder: public SyntaxTree::Visitor
|
||||
{
|
||||
private:
|
||||
virtual void visit(SyntaxTree::InitVal &) override final;
|
||||
virtual void visit(SyntaxTree::Assembly &) override final;
|
||||
virtual void visit(SyntaxTree::FuncDef &) override final;
|
||||
virtual void visit(SyntaxTree::VarDef &) override final;
|
||||
virtual void visit(SyntaxTree::AssignStmt &) override final;
|
||||
virtual void visit(SyntaxTree::ReturnStmt &) override final;
|
||||
virtual void visit(SyntaxTree::BlockStmt &) override final;
|
||||
virtual void visit(SyntaxTree::EmptyStmt &) override final;
|
||||
virtual void visit(SyntaxTree::ExprStmt &) override final;
|
||||
virtual void visit(SyntaxTree::UnaryCondExpr &) override final;
|
||||
virtual void visit(SyntaxTree::BinaryCondExpr &) override final;
|
||||
virtual void visit(SyntaxTree::BinaryExpr &) override final;
|
||||
virtual void visit(SyntaxTree::UnaryExpr &) override final;
|
||||
virtual void visit(SyntaxTree::LVal &) override final;
|
||||
virtual void visit(SyntaxTree::Literal &) override final;
|
||||
virtual void visit(SyntaxTree::FuncCallStmt &) override final;
|
||||
virtual void visit(SyntaxTree::FuncParam &) override final;
|
||||
virtual void visit(SyntaxTree::FuncFParamList &) override final;
|
||||
virtual void visit(SyntaxTree::IfStmt &) override final;
|
||||
virtual void visit(SyntaxTree::WhileStmt &) override final;
|
||||
virtual void visit(SyntaxTree::BreakStmt &) override final;
|
||||
virtual void visit(SyntaxTree::ContinueStmt &) override final;
|
||||
|
||||
Ptr<IRStmtBuilder> builder;
|
||||
Scope scope;
|
||||
Ptr<Module> module;
|
||||
|
||||
IRBuilder() {
|
||||
module = Module::create("SysYF code");
|
||||
builder = IRStmtBuilder::create(nullptr, module);
|
||||
auto TyVoid = Type::get_void_type(module);
|
||||
auto TyInt32 = Type::get_int32_type(module);
|
||||
auto TyInt32Ptr = Type::get_int32_ptr_type(module);
|
||||
auto TyFloat = Type::get_float_type(module);
|
||||
auto TyFloatPtr = Type::get_float_ptr_type(module);
|
||||
|
||||
auto input_type = FunctionType::create(TyInt32, {});
|
||||
auto get_int =
|
||||
Function::create(
|
||||
input_type,
|
||||
"get_int",
|
||||
module);
|
||||
|
||||
input_type = FunctionType::create(TyFloat, {});
|
||||
auto get_float =
|
||||
Function::create(
|
||||
input_type,
|
||||
"get_float",
|
||||
module);
|
||||
|
||||
input_type = FunctionType::create(TyInt32, {});
|
||||
auto get_char =
|
||||
Function::create(
|
||||
input_type,
|
||||
"get_char",
|
||||
module);
|
||||
|
||||
PtrVec<Type> input_params;
|
||||
PtrVec<Type> ().swap(input_params);
|
||||
input_params.push_back(TyInt32Ptr);
|
||||
input_type = FunctionType::create(TyInt32, input_params);
|
||||
auto get_int_array =
|
||||
Function::create(
|
||||
input_type,
|
||||
"get_int_array",
|
||||
module);
|
||||
|
||||
PtrVec<Type> ().swap(input_params);
|
||||
input_params.push_back(TyFloatPtr);
|
||||
input_type = FunctionType::create(TyInt32, input_params);
|
||||
auto get_float_array =
|
||||
Function::create(
|
||||
input_type,
|
||||
"get_float_array",
|
||||
module);
|
||||
|
||||
PtrVec<Type> output_params;
|
||||
PtrVec<Type> ().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
auto output_type = FunctionType::create(TyVoid, output_params);
|
||||
auto put_int =
|
||||
Function::create(
|
||||
output_type,
|
||||
"put_int",
|
||||
module);
|
||||
|
||||
PtrVec<Type> ().swap(output_params);
|
||||
output_params.push_back(TyFloat);
|
||||
output_type = FunctionType::create(TyVoid, output_params);
|
||||
auto put_float =
|
||||
Function::create(
|
||||
output_type,
|
||||
"put_float",
|
||||
module);
|
||||
|
||||
PtrVec<Type> ().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
output_type = FunctionType::create(TyVoid, output_params);
|
||||
auto put_char =
|
||||
Function::create(
|
||||
output_type,
|
||||
"put_char",
|
||||
module);
|
||||
|
||||
PtrVec<Type> ().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
output_params.push_back(TyInt32Ptr);
|
||||
output_type = FunctionType::create(TyVoid, output_params);
|
||||
auto put_int_array =
|
||||
Function::create(
|
||||
output_type,
|
||||
"put_int_array",
|
||||
module);
|
||||
|
||||
PtrVec<Type> ().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
output_params.push_back(TyFloatPtr);
|
||||
output_type = FunctionType::create(TyVoid, output_params);
|
||||
auto put_float_array =
|
||||
Function::create(
|
||||
output_type,
|
||||
"put_float_array",
|
||||
module);
|
||||
|
||||
scope.enter();
|
||||
scope.push("getint", get_int);
|
||||
scope.push("getfloat", get_float);
|
||||
scope.push("getch", get_char);
|
||||
scope.push("getarray", get_int_array);
|
||||
scope.push("get_float_array", get_float_array);
|
||||
scope.push("putint", put_int);
|
||||
scope.push("putfloat", put_float);
|
||||
scope.push("putch", put_char);
|
||||
scope.push("putarray", put_int_array);
|
||||
scope.push("putfloatarray", put_float_array);
|
||||
}
|
||||
public:
|
||||
static Ptr<IRBuilder> create() {
|
||||
return Ptr<IRBuilder>(new IRBuilder());
|
||||
}
|
||||
Ptr<Module> getModule() {
|
||||
return module;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SYSYF_IR_BUILDER_H_
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue