parent
2ca9f3d9a2
commit
262979b591
@ -0,0 +1,39 @@
|
|||||||
|
project(SysYCompiler)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -Wall -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/ASTBuilder)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ASTPrinter)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ErrorReporter)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/Grammar)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/SysYIR)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/SysYBuilder)
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/ASTBuilder)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/ASTPrinter)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/ErrorReporter)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/Grammar)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/SysYIR)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/SysYBuilder)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
SysYCompiler
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
SysYCompiler
|
||||||
|
SysYBuilder
|
||||||
|
IRLib
|
||||||
|
Driver
|
||||||
|
ASTPrinter
|
||||||
|
ErrReporter
|
||||||
|
)
|
@ -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,12 @@
|
|||||||
|
int a,b,c;
|
||||||
|
|
||||||
|
int add(int a,int b){
|
||||||
|
c=a+b;
|
||||||
|
return (c-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
a=3;
|
||||||
|
b=2;
|
||||||
|
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,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,17 @@
|
|||||||
|
project(SysYF_Task2)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
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/SysYIR)
|
||||||
|
add_subdirectory(${SYSYF_SOURCE_DIR}src/SysYIR src/SysYIR)
|
||||||
|
|
||||||
|
add_subdirectory(ta_demo)
|
||||||
|
add_subdirectory(student_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,6 @@
|
|||||||
|
int main(){
|
||||||
|
float b = 1.8;
|
||||||
|
int a[2] = {2};
|
||||||
|
a[1] = a[0] * b;
|
||||||
|
return a[1];
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
int a,b,c;
|
||||||
|
|
||||||
|
int add(int a,int b){
|
||||||
|
c=a+b;
|
||||||
|
return (c-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
a=3;
|
||||||
|
b=2;
|
||||||
|
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,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 @@
|
|||||||
|
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,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,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;
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
#!/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 = [
|
||||||
|
'./Easy_H/',
|
||||||
|
]
|
||||||
|
# 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/SysYCompiler')
|
||||||
|
testcase_list = list(map(lambda x: x.split('.'), os.listdir(TEST_BASE_PATH)))
|
||||||
|
testcase_list.sort()
|
||||||
|
for i in range(len(testcase_list)-1, -1, -1):
|
||||||
|
if len(testcase_list[i]) == 1:
|
||||||
|
testcase_list.remove(testcase_list[i])
|
||||||
|
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)
|
Binary file not shown.
@ -0,0 +1,17 @@
|
|||||||
|
# 组员贡献
|
||||||
|
|
||||||
|
## 贡献详述
|
||||||
|
|
||||||
|
### 组员1 张三
|
||||||
|
|
||||||
|
### 组员2 李四
|
||||||
|
|
||||||
|
### 组员3 王五
|
||||||
|
|
||||||
|
## 评定结果
|
||||||
|
|
||||||
|
| 组员姓名 | 贡献百分比 |
|
||||||
|
| :-----: | :-------: |
|
||||||
|
| 张三 | xx% |
|
||||||
|
| 李四 | xx% |
|
||||||
|
| 王五 | xx% |
|
@ -0,0 +1,333 @@
|
|||||||
|
#ifndef _SYSY_SYNTAX_TREE_H_
|
||||||
|
#define _SYSY_SYNTAX_TREE_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "location.hh"
|
||||||
|
|
||||||
|
namespace SyntaxTree
|
||||||
|
{
|
||||||
|
// Use unique postd::stringtype to reference stored objects
|
||||||
|
template <typename T>
|
||||||
|
using Ptr = std::shared_ptr<T>;
|
||||||
|
|
||||||
|
// List of reference of type
|
||||||
|
template <typename T>
|
||||||
|
using PtrList = std::vector<Ptr<T>>;
|
||||||
|
|
||||||
|
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;
|
||||||
|
PtrList<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
|
||||||
|
{
|
||||||
|
PtrList<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 `{}`
|
||||||
|
PtrList<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
|
||||||
|
{
|
||||||
|
PtrList<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;
|
||||||
|
PtrList<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;
|
||||||
|
PtrList<Expr> params;
|
||||||
|
void accept(Visitor &visitor) final;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FuncParam : Node
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
Type param_type;
|
||||||
|
PtrList<Expr> array_index; // nullptr if not indexed as array
|
||||||
|
void accept(Visitor &visitor) final;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FuncFParamList : Node
|
||||||
|
{
|
||||||
|
PtrList<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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// end namespace SyntaxTree
|
||||||
|
|
||||||
|
#endif // _SYSY_SYNTAX_TREE_H_
|
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _SYSY_SYNTAX_TREE_PRINTER_H_
|
||||||
|
#define _SYSY_SYNTAX_TREE_PRINTER_H_
|
||||||
|
|
||||||
|
#include "SyntaxTree.h"
|
||||||
|
|
||||||
|
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 // _SYSY_SYNTAX_TREE_PRINTER_H_
|
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#ifndef _SYSY_ERROR_REPORTER_H_
|
||||||
|
#define _SYSY_ERROR_REPORTER_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <deque>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include "SyntaxTree.h"
|
||||||
|
|
||||||
|
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 // _SYSY_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 _SYSY_DRIVER_H_
|
||||||
|
#define _SYSY_DRIVER_H_
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// Generated by bison:
|
||||||
|
#include "SysYParser.h"
|
||||||
|
|
||||||
|
#include "SysYFlexLexer.h"
|
||||||
|
|
||||||
|
// Conducting the whole scanning and parsing of SysY.
|
||||||
|
class SysYDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SysYDriver();
|
||||||
|
virtual ~SysYDriver();
|
||||||
|
|
||||||
|
std::map<std::string, int> variables;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
// SysY lexer
|
||||||
|
SysYFlexLexer lexer;
|
||||||
|
|
||||||
|
std::ifstream instream;
|
||||||
|
|
||||||
|
// Handling the SysY scanner.
|
||||||
|
void scan_begin();
|
||||||
|
void scan_end();
|
||||||
|
bool trace_scanning;
|
||||||
|
|
||||||
|
// Run the parser on file F.
|
||||||
|
// Return 0 on success.
|
||||||
|
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);
|
||||||
|
|
||||||
|
SyntaxTree::Node* root = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_DRIVER_H_
|
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef _SYSY_FLEX_LEXER_H_
|
||||||
|
#define _SYSY_FLEX_LEXER_H_
|
||||||
|
|
||||||
|
#ifndef YY_DECL
|
||||||
|
#define YY_DECL \
|
||||||
|
yy::SysYParser::symbol_type SysYFlexLexer::yylex(SysYDriver& 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::SysYParser::symbol_type:
|
||||||
|
#include "SysYParser.h"
|
||||||
|
|
||||||
|
// We need this for the yy::location type:
|
||||||
|
#include "location.hh"
|
||||||
|
|
||||||
|
class SysYFlexLexer : public yyFlexLexer {
|
||||||
|
public:
|
||||||
|
// Use the superclass's constructor:
|
||||||
|
using yyFlexLexer::yyFlexLexer;
|
||||||
|
|
||||||
|
// Provide the interface to `yylex`; `flex` will emit the
|
||||||
|
// definition into `SysYScanner.cpp`:
|
||||||
|
yy::SysYParser::symbol_type yylex(SysYDriver& 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 // _SYSY_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.7.6.
|
||||||
|
|
||||||
|
// 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 /home/hzq/SysYF_IR_Lab/2021_sysycompiler_ir_lab/build/location.hh
|
||||||
|
** Define the yy::location class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef YY_YY_HOME_HZQ_SYSYF_IR_LAB_2021_SYSYCOMPILER_IR_LAB_BUILD_LOCATION_HH_INCLUDED
|
||||||
|
# define YY_YY_HOME_HZQ_SYSYF_IR_LAB_2021_SYSYCOMPILER_IR_LAB_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 "/home/hzq/SysYF_IR_Lab/2021_sysycompiler_ir_lab/build/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 "/home/hzq/SysYF_IR_Lab/2021_sysycompiler_ir_lab/build/location.hh"
|
||||||
|
|
||||||
|
#endif // !YY_YY_HOME_HZQ_SYSYF_IR_LAB_2021_SYSYCOMPILER_IR_LAB_BUILD_LOCATION_HH_INCLUDED
|
@ -0,0 +1,11 @@
|
|||||||
|
// A Bison parser, made by GNU Bison 3.7.6.
|
||||||
|
|
||||||
|
// 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.7.6.
|
||||||
|
|
||||||
|
// 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,217 @@
|
|||||||
|
#ifndef _SYSY_IR_BUILDER_HPP_
|
||||||
|
#define _SYSY_IR_BUILDER_HPP_
|
||||||
|
#include "BasicBlock.h"
|
||||||
|
#include "Constant.h"
|
||||||
|
#include "Function.h"
|
||||||
|
#include "IRBuilder.h"
|
||||||
|
#include "Module.h"
|
||||||
|
#include "Type.h"
|
||||||
|
#include <map>
|
||||||
|
#include "SyntaxTree.h"
|
||||||
|
|
||||||
|
|
||||||
|
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, Value *val) {
|
||||||
|
bool result;
|
||||||
|
if (dynamic_cast<Function *>(val)){
|
||||||
|
result = (name2func[name2func.size() - 1].insert({name, val})).second;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = (name2var[name2var.size() - 1].insert({name, val})).second;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, Value *>> name2var;
|
||||||
|
std::vector<std::map<std::string, Value *>> name2func;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SysYBuilder: 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;
|
||||||
|
|
||||||
|
IRBuilder *builder;
|
||||||
|
Scope scope;
|
||||||
|
std::unique_ptr<Module> module;
|
||||||
|
public:
|
||||||
|
SysYBuilder(){
|
||||||
|
module = std::unique_ptr<Module>(new Module("SysY code"));
|
||||||
|
builder = new IRBuilder(nullptr, module.get());
|
||||||
|
auto TyVoid = Type::get_void_type(module.get());
|
||||||
|
auto TyInt32 = Type::get_int32_type(module.get());
|
||||||
|
auto TyInt32Ptr = Type::get_int32_ptr_type(module.get());
|
||||||
|
auto TyFloat = Type::get_float_type(module.get());
|
||||||
|
auto TyFloatPtr = Type::get_float_ptr_type(module.get());
|
||||||
|
|
||||||
|
auto input_type = FunctionType::get(TyInt32, {});
|
||||||
|
auto get_int =
|
||||||
|
Function::create(
|
||||||
|
input_type,
|
||||||
|
"get_int",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
input_type = FunctionType::get(TyFloat, {});
|
||||||
|
auto get_float =
|
||||||
|
Function::create(
|
||||||
|
input_type,
|
||||||
|
"get_float",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
input_type = FunctionType::get(TyInt32, {});
|
||||||
|
auto get_char =
|
||||||
|
Function::create(
|
||||||
|
input_type,
|
||||||
|
"get_char",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *> input_params;
|
||||||
|
std::vector<Type *>().swap(input_params);
|
||||||
|
input_params.push_back(TyInt32Ptr);
|
||||||
|
input_type = FunctionType::get(TyInt32, input_params);
|
||||||
|
auto get_int_array =
|
||||||
|
Function::create(
|
||||||
|
input_type,
|
||||||
|
"get_int_array",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *>().swap(input_params);
|
||||||
|
input_params.push_back(TyFloatPtr);
|
||||||
|
input_type = FunctionType::get(TyInt32, input_params);
|
||||||
|
auto get_float_array =
|
||||||
|
Function::create(
|
||||||
|
input_type,
|
||||||
|
"get_float_array",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *> output_params;
|
||||||
|
std::vector<Type *>().swap(output_params);
|
||||||
|
output_params.push_back(TyInt32);
|
||||||
|
auto output_type = FunctionType::get(TyVoid, output_params);
|
||||||
|
auto put_int =
|
||||||
|
Function::create(
|
||||||
|
output_type,
|
||||||
|
"put_int",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *>().swap(output_params);
|
||||||
|
output_params.push_back(TyFloat);
|
||||||
|
output_type = FunctionType::get(TyVoid, output_params);
|
||||||
|
auto put_float =
|
||||||
|
Function::create(
|
||||||
|
output_type,
|
||||||
|
"put_float",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *>().swap(output_params);
|
||||||
|
output_params.push_back(TyInt32);
|
||||||
|
output_type = FunctionType::get(TyVoid, output_params);
|
||||||
|
auto put_char =
|
||||||
|
Function::create(
|
||||||
|
output_type,
|
||||||
|
"put_char",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *>().swap(output_params);
|
||||||
|
output_params.push_back(TyInt32);
|
||||||
|
output_params.push_back(TyInt32Ptr);
|
||||||
|
output_type = FunctionType::get(TyVoid, output_params);
|
||||||
|
auto put_int_array =
|
||||||
|
Function::create(
|
||||||
|
output_type,
|
||||||
|
"put_int_array",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
std::vector<Type *>().swap(output_params);
|
||||||
|
output_params.push_back(TyInt32);
|
||||||
|
output_params.push_back(TyFloatPtr);
|
||||||
|
output_type = FunctionType::get(TyVoid, output_params);
|
||||||
|
auto put_float_array =
|
||||||
|
Function::create(
|
||||||
|
output_type,
|
||||||
|
"put_float_array",
|
||||||
|
module.get());
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
std::unique_ptr<Module> getModule() {
|
||||||
|
return std::move(module);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _SYSY_IR_BUILDER_HPP_
|
@ -0,0 +1,77 @@
|
|||||||
|
#ifndef _SYSY_BASICBLOCK_H_
|
||||||
|
#define _SYSY_BASICBLOCK_H_
|
||||||
|
|
||||||
|
#include "Value.h"
|
||||||
|
#include "Instruction.h"
|
||||||
|
#include "Module.h"
|
||||||
|
#include "Function.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Function;
|
||||||
|
class Instruction;
|
||||||
|
class Module;
|
||||||
|
|
||||||
|
class BasicBlock : public Value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BasicBlock *create(Module *m, const std::string &name ,
|
||||||
|
Function *parent ) {
|
||||||
|
auto prefix = name.empty() ? "" : "label_";
|
||||||
|
return new BasicBlock(m, prefix + name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return parent, or null if none.
|
||||||
|
Function *get_parent() { return parent_; }
|
||||||
|
|
||||||
|
Module *get_module();
|
||||||
|
|
||||||
|
/****************api about cfg****************/
|
||||||
|
|
||||||
|
std::list<BasicBlock *> &get_pre_basic_blocks() { return pre_bbs_; }
|
||||||
|
std::list<BasicBlock *> &get_succ_basic_blocks() { return succ_bbs_; }
|
||||||
|
void add_pre_basic_block(BasicBlock *bb) { pre_bbs_.push_back(bb); }
|
||||||
|
void add_succ_basic_block(BasicBlock *bb) { succ_bbs_.push_back(bb); }
|
||||||
|
|
||||||
|
void remove_pre_basic_block(BasicBlock *bb) { pre_bbs_.remove(bb); }
|
||||||
|
void remove_succ_basic_block(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 Instruction *get_terminator() const;
|
||||||
|
Instruction *get_terminator() {
|
||||||
|
return const_cast<Instruction *>(
|
||||||
|
static_cast<const BasicBlock *>(this)->get_terminator());
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_instruction(Instruction *instr);
|
||||||
|
void add_instruction(std::list<Instruction *>::iterator instr_pos, Instruction *instr);
|
||||||
|
void add_instr_begin(Instruction *instr);
|
||||||
|
|
||||||
|
std::list<Instruction *>::iterator find_instruction(Instruction *instr);
|
||||||
|
|
||||||
|
void delete_instr(Instruction *instr);
|
||||||
|
|
||||||
|
bool empty() { return instr_list_.empty(); }
|
||||||
|
|
||||||
|
int get_num_of_instr() { return instr_list_.size(); }
|
||||||
|
std::list<Instruction *> &get_instructions() { return instr_list_; }
|
||||||
|
|
||||||
|
void erase_from_parent();
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit BasicBlock(Module *m, const std::string &name ,
|
||||||
|
Function *parent );
|
||||||
|
std::list<BasicBlock *> pre_bbs_;
|
||||||
|
std::list<BasicBlock *> succ_bbs_;
|
||||||
|
std::list<Instruction *> instr_list_;
|
||||||
|
Function *parent_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_BASICBLOCK_H_
|
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef _SYSY_CONSTANT_H_
|
||||||
|
#define _SYSY_CONSTANT_H_
|
||||||
|
#include "User.h"
|
||||||
|
#include "Value.h"
|
||||||
|
#include "Type.h"
|
||||||
|
|
||||||
|
class Constant : public User
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// int value;
|
||||||
|
public:
|
||||||
|
Constant(Type *ty, const std::string &name = "", unsigned num_ops = 0)
|
||||||
|
: User(ty, name, num_ops) {}
|
||||||
|
~Constant() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantInt : public Constant
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int value_;
|
||||||
|
ConstantInt(Type* ty,int val)
|
||||||
|
: Constant(ty,"",0),value_(val) {}
|
||||||
|
public:
|
||||||
|
|
||||||
|
static int get_value(ConstantInt *const_val) { return const_val->value_; }
|
||||||
|
int get_value() { return value_; }
|
||||||
|
static ConstantInt *get(int val, Module *m);
|
||||||
|
static ConstantInt *get(bool val, Module *m);
|
||||||
|
virtual std::string print() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantFloat : public Constant
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float value_;
|
||||||
|
ConstantFloat(Type* ty,float val)
|
||||||
|
: Constant(ty,"",0),value_(val) {}
|
||||||
|
public:
|
||||||
|
|
||||||
|
static float get_value(ConstantFloat *const_val) { return const_val->value_; }
|
||||||
|
float get_value() { return value_; }
|
||||||
|
static ConstantFloat *get(float val, Module *m);
|
||||||
|
virtual std::string print() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantArray : public Constant
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<Constant*> const_array;
|
||||||
|
|
||||||
|
ConstantArray(ArrayType *ty, const std::vector<Constant*> &val);
|
||||||
|
public:
|
||||||
|
|
||||||
|
~ConstantArray()=default;
|
||||||
|
|
||||||
|
Constant* get_element_value(int index);
|
||||||
|
|
||||||
|
unsigned get_size_of_array() { return const_array.size(); }
|
||||||
|
|
||||||
|
static ConstantArray *get(ArrayType *ty, const std::vector<Constant*> &val);
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstantZero : public Constant
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ConstantZero(Type *ty)
|
||||||
|
: Constant(ty,"",0) {}
|
||||||
|
public:
|
||||||
|
static ConstantZero *get(Type *ty, Module *m);
|
||||||
|
virtual std::string print() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_SYSY_CONSTANT_H_
|
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef _SYSY_FUNCTION_H_
|
||||||
|
#define _SYSY_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"
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
class Argument;
|
||||||
|
class BasicBlock;
|
||||||
|
class Type;
|
||||||
|
class FunctionType;
|
||||||
|
|
||||||
|
class Function : public Value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Function(FunctionType *ty, const std::string &name, Module *parent);
|
||||||
|
~Function();
|
||||||
|
static Function *create(FunctionType *ty, const std::string &name, Module *parent);
|
||||||
|
|
||||||
|
FunctionType *get_function_type() const;
|
||||||
|
|
||||||
|
Type *get_return_type() const;
|
||||||
|
|
||||||
|
void add_basic_block(BasicBlock *bb);
|
||||||
|
|
||||||
|
unsigned get_num_of_args() const;
|
||||||
|
unsigned get_num_basic_blocks() const;
|
||||||
|
|
||||||
|
Module *get_parent() const;
|
||||||
|
|
||||||
|
std::list<Argument *>::iterator arg_begin() { return arguments_.begin(); }
|
||||||
|
std::list<Argument *>::iterator arg_end() { return arguments_.end(); }
|
||||||
|
|
||||||
|
void remove(BasicBlock* bb);
|
||||||
|
BasicBlock *get_entry_block() { return *basic_blocks_.begin(); }
|
||||||
|
|
||||||
|
std::list<BasicBlock *> &get_basic_blocks() { return basic_blocks_; }
|
||||||
|
std::list<Argument *> &get_args() { return arguments_; }
|
||||||
|
std::vector<std::set<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:
|
||||||
|
void build_args();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<BasicBlock *> basic_blocks_; // basic blocks
|
||||||
|
std::list<Argument *> arguments_; // arguments
|
||||||
|
std::vector<std::set<Value *>> vreg_set_;
|
||||||
|
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, Value*> sym_table_; // Symbol table of args/instructions
|
||||||
|
};
|
||||||
|
|
||||||
|
// Argument of Function, does not contain actual value
|
||||||
|
class Argument : public Value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Argument constructor.
|
||||||
|
explicit Argument(Type *ty, const std::string &name = "", Function *f = nullptr,
|
||||||
|
unsigned arg_no = 0)
|
||||||
|
: Value(ty, name), parent_(f), arg_no_(arg_no) {}
|
||||||
|
~Argument() {}
|
||||||
|
|
||||||
|
inline const Function *get_parent() const { return parent_; }
|
||||||
|
inline 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:
|
||||||
|
Function *parent_;
|
||||||
|
unsigned arg_no_; // argument No.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_FUNCTION_H_
|
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _SYSY_GLOBALVARIABLE_H_
|
||||||
|
#define _SYSY_GLOBALVARIABLE_H_
|
||||||
|
|
||||||
|
#include "Module.h"
|
||||||
|
#include "User.h"
|
||||||
|
#include "Constant.h"
|
||||||
|
|
||||||
|
class GlobalVariable : public User
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool is_const_ ;
|
||||||
|
Constant* init_val_;
|
||||||
|
GlobalVariable(std::string name, Module *m, Type* ty, bool is_const, Constant* init = nullptr);
|
||||||
|
public:
|
||||||
|
static GlobalVariable *create(std::string name, Module *m, Type* ty, bool is_const,
|
||||||
|
Constant* init );
|
||||||
|
|
||||||
|
Constant *get_init() { return init_val_; }
|
||||||
|
bool is_const() { return is_const_; }
|
||||||
|
std::string print();
|
||||||
|
};
|
||||||
|
#endif //_SYSY_GLOBALVARIABLE_H_
|
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef _SYSY_IRBUILDER_H_
|
||||||
|
#define _SYSY_IRBUILDER_H_
|
||||||
|
|
||||||
|
#include "BasicBlock.h"
|
||||||
|
#include "Instruction.h"
|
||||||
|
#include "Value.h"
|
||||||
|
|
||||||
|
class IRBuilder {
|
||||||
|
private:
|
||||||
|
BasicBlock *BB_;
|
||||||
|
Module *m_;
|
||||||
|
public:
|
||||||
|
IRBuilder(BasicBlock *bb, Module *m) : BB_(bb), m_(m) {};
|
||||||
|
~IRBuilder() = default;
|
||||||
|
Module *get_module(){return m_;}
|
||||||
|
BasicBlock *get_insert_block() { return this->BB_; }
|
||||||
|
void set_insert_point(BasicBlock *bb) { this->BB_ = bb; } //在某个基本块中插入指令
|
||||||
|
BinaryInst *create_iadd( Value *lhs, Value *rhs){ return BinaryInst::create_add( lhs, rhs, this->BB_, m_);} //创建加法指令(以及其他算术指令)
|
||||||
|
BinaryInst *create_isub( Value *lhs, Value *rhs){ return BinaryInst::create_sub( lhs, rhs, this->BB_, m_);}
|
||||||
|
BinaryInst *create_imul( Value *lhs, Value *rhs){ return BinaryInst::create_mul( lhs, rhs, this->BB_, m_);}
|
||||||
|
BinaryInst *create_isdiv( Value *lhs, Value *rhs){ return BinaryInst::create_sdiv( lhs, rhs, this->BB_, m_);}
|
||||||
|
BinaryInst *create_isrem( Value *lhs, Value *rhs){ return BinaryInst::create_srem( lhs, rhs, this->BB_, m_);}
|
||||||
|
|
||||||
|
CmpInst *create_icmp_eq( Value *lhs, Value *rhs){ return CmpInst::create_cmp(CmpInst::EQ, lhs, rhs, this->BB_, m_); }
|
||||||
|
CmpInst *create_icmp_ne( Value *lhs, Value *rhs){ return CmpInst::create_cmp(CmpInst::NE, lhs, rhs, this->BB_, m_); }
|
||||||
|
CmpInst *create_icmp_gt( Value *lhs, Value *rhs){ return CmpInst::create_cmp(CmpInst::GT, lhs, rhs, this->BB_, m_); }
|
||||||
|
CmpInst *create_icmp_ge( Value *lhs, Value *rhs){ return CmpInst::create_cmp(CmpInst::GE, lhs, rhs, this->BB_, m_); }
|
||||||
|
CmpInst *create_icmp_lt( Value *lhs, Value *rhs){ return CmpInst::create_cmp(CmpInst::LT, lhs, rhs, this->BB_, m_); }
|
||||||
|
CmpInst *create_icmp_le( Value *lhs, Value *rhs){ return CmpInst::create_cmp(CmpInst::LE, lhs, rhs, this->BB_, m_); }
|
||||||
|
|
||||||
|
BinaryInst *create_fadd( Value *lhs, Value *rhs){ return BinaryInst::create_fadd( lhs, rhs, this->BB_, m_);}
|
||||||
|
BinaryInst *create_fsub( Value *lhs, Value *rhs){ return BinaryInst::create_fsub( lhs, rhs, this->BB_, m_);}
|
||||||
|
BinaryInst *create_fmul( Value *lhs, Value *rhs){ return BinaryInst::create_fmul( lhs, rhs, this->BB_, m_);}
|
||||||
|
BinaryInst *create_fdiv( Value *lhs, Value *rhs){ return BinaryInst::create_fdiv( lhs, rhs, this->BB_, m_);}
|
||||||
|
|
||||||
|
FCmpInst *create_fcmp_eq( Value *lhs, Value *rhs){ return FCmpInst::create_fcmp(FCmpInst::EQ, lhs, rhs, this->BB_, m_); }
|
||||||
|
FCmpInst *create_fcmp_ne( Value *lhs, Value *rhs){ return FCmpInst::create_fcmp(FCmpInst::NE, lhs, rhs, this->BB_, m_); }
|
||||||
|
FCmpInst *create_fcmp_gt( Value *lhs, Value *rhs){ return FCmpInst::create_fcmp(FCmpInst::GT, lhs, rhs, this->BB_, m_); }
|
||||||
|
FCmpInst *create_fcmp_ge( Value *lhs, Value *rhs){ return FCmpInst::create_fcmp(FCmpInst::GE, lhs, rhs, this->BB_, m_); }
|
||||||
|
FCmpInst *create_fcmp_lt( Value *lhs, Value *rhs){ return FCmpInst::create_fcmp(FCmpInst::LT, lhs, rhs, this->BB_, m_); }
|
||||||
|
FCmpInst *create_fcmp_le( Value *lhs, Value *rhs){ return FCmpInst::create_fcmp(FCmpInst::LE, lhs, rhs, this->BB_, m_); }
|
||||||
|
|
||||||
|
CallInst *create_call(Value *func, std::vector<Value *> args)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert( dynamic_cast<Function *>(func) && "func must be Function * type");
|
||||||
|
#endif
|
||||||
|
return CallInst::create(static_cast<Function *>(func) ,args, this->BB_);
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchInst *create_br(BasicBlock *if_true){ return BranchInst::create_br(if_true, this->BB_); }
|
||||||
|
BranchInst *create_cond_br(Value *cond, BasicBlock *if_true, BasicBlock *if_false){ return BranchInst::create_cond_br(cond, if_true, if_false,this->BB_); }
|
||||||
|
|
||||||
|
ReturnInst *create_ret(Value *val) { return ReturnInst::create_ret(val,this->BB_); }
|
||||||
|
ReturnInst *create_void_ret() { return ReturnInst::create_void_ret(this->BB_); }
|
||||||
|
|
||||||
|
GetElementPtrInst *create_gep(Value *ptr, std::vector<Value *> idxs) { return GetElementPtrInst::create_gep(ptr, idxs, this->BB_); }
|
||||||
|
|
||||||
|
StoreInst *create_store(Value *val, Value *ptr) { return StoreInst::create_store(val, ptr, this->BB_ ); }
|
||||||
|
LoadInst * create_load(Type *ty, Value *ptr) { return LoadInst::create_load(ty, ptr, this->BB_); }
|
||||||
|
LoadInst * create_load(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_);
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocaInst *create_alloca(Type *ty) { return AllocaInst::create_alloca(ty, this->BB_); }
|
||||||
|
ZextInst *create_zext(Value *val, Type *ty) { return ZextInst::create_zext(val, ty, this->BB_); }
|
||||||
|
FpToSiInst *create_fptosi(Value *val, Type *ty) { return FpToSiInst::create_fptosi(val, ty, this->BB_); }
|
||||||
|
SiToFpInst *create_sitofp(Value *val, Type *ty) { return SiToFpInst::create_sitofp(val, ty, this->BB_); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_IRBUILDER_H_
|
@ -0,0 +1,13 @@
|
|||||||
|
#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"
|
||||||
|
|
||||||
|
std::string print_as_op( Value *v, bool print_ty );
|
||||||
|
std::string print_cmp_type( CmpInst::CmpOp op);
|
||||||
|
std::string print_fcmp_type( FCmpInst::CmpOp op);
|
@ -0,0 +1,405 @@
|
|||||||
|
#ifndef _SYSY_INSTRUCTION_H_
|
||||||
|
#define _SYSY_INSTRUCTION_H_
|
||||||
|
|
||||||
|
#include "User.h"
|
||||||
|
#include "Type.h"
|
||||||
|
#include "Constant.h"
|
||||||
|
#include "BasicBlock.h"
|
||||||
|
|
||||||
|
class BasicBlock;
|
||||||
|
class Function;
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
// create instruction, auto insert to bb
|
||||||
|
// ty here is result type
|
||||||
|
Instruction(Type *ty, OpID id, unsigned num_ops,
|
||||||
|
BasicBlock *parent);
|
||||||
|
Instruction(Type *ty, OpID id, unsigned num_ops);
|
||||||
|
inline const BasicBlock *get_parent() const { return parent_; }
|
||||||
|
inline BasicBlock *get_parent() { return parent_; }
|
||||||
|
void set_parent(BasicBlock *parent) { this->parent_ = parent; }
|
||||||
|
// Return the function this instruction belongs to.
|
||||||
|
Function *get_function();
|
||||||
|
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:
|
||||||
|
BasicBlock *parent_;
|
||||||
|
OpID op_id_;
|
||||||
|
int id_;
|
||||||
|
unsigned num_ops_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinaryInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
BinaryInst(Type *ty, OpID id, Value *v1, Value *v2,
|
||||||
|
BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static BinaryInst *create_add(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_sub(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_mul(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_sdiv(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_srem(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_fadd(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_fsub(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_fmul(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
static BinaryInst *create_fdiv(Value *v1, Value *v2, BasicBlock *bb, Module *m);
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void assertValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
class CmpInst : public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum CmpOp
|
||||||
|
{
|
||||||
|
EQ, // ==
|
||||||
|
NE, // !=
|
||||||
|
GT, // >
|
||||||
|
GE, // >=
|
||||||
|
LT, // <
|
||||||
|
LE // <=
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
CmpInst(Type *ty, CmpOp op, Value *lhs, Value *rhs,
|
||||||
|
BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CmpInst *create_cmp(CmpOp op, Value *lhs, Value *rhs,
|
||||||
|
BasicBlock *bb, Module *m);
|
||||||
|
|
||||||
|
CmpOp get_cmp_op() { return cmp_op_; }
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CmpOp cmp_op_;
|
||||||
|
|
||||||
|
void assertValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
class FCmpInst : public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum CmpOp
|
||||||
|
{
|
||||||
|
EQ, // ==
|
||||||
|
NE, // !=
|
||||||
|
GT, // >
|
||||||
|
GE, // >=
|
||||||
|
LT, // <
|
||||||
|
LE // <=
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
FCmpInst(Type *ty, CmpOp op, Value *lhs, Value *rhs,
|
||||||
|
BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static FCmpInst *create_fcmp(CmpOp op, Value *lhs, Value *rhs,
|
||||||
|
BasicBlock *bb, Module *m);
|
||||||
|
|
||||||
|
CmpOp get_cmp_op() { return cmp_op_; }
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CmpOp cmp_op_;
|
||||||
|
|
||||||
|
void assertValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
class CallInst : public Instruction
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
CallInst(Function *func, std::vector<Value *> args, BasicBlock *bb);
|
||||||
|
CallInst(Type *ret_ty, std::vector<Value *> args, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CallInst *create(Function *func, std::vector<Value *> args, BasicBlock *bb);
|
||||||
|
FunctionType *get_function_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class BranchInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
BranchInst(Value *cond, BasicBlock *if_true, BasicBlock *if_false,
|
||||||
|
BasicBlock *bb);
|
||||||
|
BranchInst(Value *cond, BasicBlock *bb);
|
||||||
|
BranchInst(BasicBlock *if_true, BasicBlock *bb);
|
||||||
|
BranchInst(BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static BranchInst *create_cond_br(Value *cond, BasicBlock *if_true, BasicBlock *if_false,
|
||||||
|
BasicBlock *bb);
|
||||||
|
static BranchInst *create_br(BasicBlock *if_true, BasicBlock *bb);
|
||||||
|
|
||||||
|
bool is_cond_br() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReturnInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReturnInst(Value *val, BasicBlock *bb);
|
||||||
|
ReturnInst(BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ReturnInst *create_ret(Value *val, BasicBlock *bb);
|
||||||
|
static ReturnInst *create_void_ret(BasicBlock *bb);
|
||||||
|
bool is_void_ret() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class GetElementPtrInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
GetElementPtrInst(Value *ptr, std::vector<Value *> idxs, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Type *get_element_type(Value *ptr, std::vector<Value *> idxs);
|
||||||
|
static GetElementPtrInst *create_gep(Value *ptr, std::vector<Value *> idxs, BasicBlock *bb);
|
||||||
|
Type *get_element_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *element_ty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StoreInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
StoreInst(Value *val, Value *ptr, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static StoreInst *create_store(Value *val, Value *ptr, BasicBlock *bb);
|
||||||
|
|
||||||
|
Value *get_rval() { return this->get_operand(0); }
|
||||||
|
Value *get_lval() { return this->get_operand(1); }
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoadInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
LoadInst(Type *ty, Value *ptr, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static LoadInst *create_load(Type *ty, Value *ptr, BasicBlock *bb);
|
||||||
|
Value *get_lval() { return this->get_operand(0); }
|
||||||
|
|
||||||
|
Type *get_load_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class AllocaInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
AllocaInst(Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static AllocaInst *create_alloca(Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
Type *get_alloca_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *alloca_ty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ZextInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ZextInst(OpID op, Value *val, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ZextInst *create_zext(Value *val, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
Type *get_dest_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *dest_ty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FpToSiInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
FpToSiInst(OpID op, Value *val, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static FpToSiInst *create_fptosi(Value *val, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
Type *get_dest_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *dest_ty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SiToFpInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SiToFpInst(OpID op, Value *val, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static SiToFpInst *create_sitofp(Value *val, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
Type *get_dest_type() const;
|
||||||
|
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *dest_ty_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PhiInst : public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
PhiInst(OpID op, std::vector<Value *> vals, std::vector<BasicBlock *> val_bbs, Type *ty, BasicBlock *bb);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static PhiInst *create_phi(Type *ty, BasicBlock *bb);
|
||||||
|
Value *get_lval() { return l_val_; }
|
||||||
|
void set_lval(Value *l_val) { l_val_ = l_val; }
|
||||||
|
void add_phi_pair_operand(Value *val, Value *pre_bb)
|
||||||
|
{
|
||||||
|
this->add_operand(val);
|
||||||
|
this->add_operand(pre_bb);
|
||||||
|
}
|
||||||
|
virtual std::string print() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Value *l_val_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_INSTRUCTION_H_
|
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef _SYSY_MODULE_H_
|
||||||
|
#define _SYSY_MODULE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Type.h"
|
||||||
|
#include "GlobalVariable.h"
|
||||||
|
#include "Value.h"
|
||||||
|
#include "Function.h"
|
||||||
|
|
||||||
|
class GlobalVariable;
|
||||||
|
|
||||||
|
class Module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Module(std::string name);
|
||||||
|
~Module();
|
||||||
|
|
||||||
|
Type *get_void_type();
|
||||||
|
Type *get_label_type();
|
||||||
|
IntegerType *get_int1_type();
|
||||||
|
IntegerType *get_int32_type();
|
||||||
|
FloatType *get_float_type();
|
||||||
|
PointerType *get_int32_ptr_type();
|
||||||
|
PointerType *get_float_ptr_type();
|
||||||
|
|
||||||
|
PointerType *get_pointer_type(Type *contained);
|
||||||
|
ArrayType *get_array_type(Type *contained, unsigned num_elements);
|
||||||
|
|
||||||
|
void add_function(Function *f);
|
||||||
|
std::list<Function* > &get_functions();
|
||||||
|
void add_global_variable(GlobalVariable* g);
|
||||||
|
std::list<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:
|
||||||
|
std::list<GlobalVariable *> global_list_; // The Global Variables in the module
|
||||||
|
std::list<Function *> function_list_; // The Functions in the module
|
||||||
|
std::map<std::string, 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:
|
||||||
|
IntegerType *int1_ty_;
|
||||||
|
IntegerType *int32_ty_;
|
||||||
|
FloatType *float32_ty_;
|
||||||
|
Type *label_ty_;
|
||||||
|
Type *void_ty_;
|
||||||
|
|
||||||
|
std::map<Type *, PointerType *> pointer_map_;
|
||||||
|
std::map<std::pair<Type *,int >, ArrayType *> array_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_MODULE_H_
|
@ -0,0 +1,146 @@
|
|||||||
|
#ifndef _SYSY_TYPE_H_
|
||||||
|
#define _SYSY_TYPE_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
class IntegerType;
|
||||||
|
class FloatType;
|
||||||
|
class FunctionType;
|
||||||
|
class ArrayType;
|
||||||
|
class PointerType;
|
||||||
|
|
||||||
|
class 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
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Type(TypeID tid, 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(Type *ty1, Type *ty2);
|
||||||
|
|
||||||
|
static Type *get_void_type(Module *m);
|
||||||
|
|
||||||
|
static Type *get_label_type(Module *m);
|
||||||
|
|
||||||
|
static IntegerType *get_int1_type(Module *m);
|
||||||
|
|
||||||
|
static IntegerType *get_int32_type(Module *m);
|
||||||
|
|
||||||
|
static FloatType *get_float_type(Module *m);
|
||||||
|
|
||||||
|
static PointerType *get_int32_ptr_type(Module *m);
|
||||||
|
|
||||||
|
static PointerType *get_float_ptr_type(Module *m);
|
||||||
|
|
||||||
|
static PointerType *get_pointer_type(Type *contained);
|
||||||
|
|
||||||
|
static ArrayType *get_array_type(Type *contained, unsigned num_elements);
|
||||||
|
|
||||||
|
Type *get_pointer_element_type();
|
||||||
|
|
||||||
|
Type *get_array_element_type();
|
||||||
|
|
||||||
|
int get_size();
|
||||||
|
|
||||||
|
Module *get_module();
|
||||||
|
|
||||||
|
std::string print();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TypeID tid_;
|
||||||
|
Module *m_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IntegerType : public Type {
|
||||||
|
public:
|
||||||
|
explicit IntegerType(unsigned num_bits ,Module *m);
|
||||||
|
|
||||||
|
static IntegerType *get(unsigned num_bits, Module *m );
|
||||||
|
|
||||||
|
unsigned get_num_bits();
|
||||||
|
private:
|
||||||
|
unsigned num_bits_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FloatType : public Type {
|
||||||
|
public:
|
||||||
|
FloatType(Module *m);
|
||||||
|
static FloatType *get(Module *m );
|
||||||
|
};
|
||||||
|
|
||||||
|
class FunctionType : public Type {
|
||||||
|
public:
|
||||||
|
FunctionType(Type *result, std::vector<Type *> params);
|
||||||
|
|
||||||
|
static bool is_valid_return_type(Type *ty);
|
||||||
|
static bool is_valid_argument_type(Type *ty);
|
||||||
|
|
||||||
|
static FunctionType *get(Type *result,
|
||||||
|
std::vector<Type*> params);
|
||||||
|
|
||||||
|
unsigned get_num_of_args() const;
|
||||||
|
|
||||||
|
Type *get_param_type(unsigned i) const;
|
||||||
|
std::vector<Type *>::iterator param_begin() { return args_.begin(); }
|
||||||
|
std::vector<Type *>::iterator param_end() { return args_.end(); }
|
||||||
|
Type *get_return_type() const;
|
||||||
|
private:
|
||||||
|
Type *result_;
|
||||||
|
std::vector<Type *> args_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArrayType : public Type {
|
||||||
|
public:
|
||||||
|
ArrayType(Type *contained, unsigned num_elements);
|
||||||
|
|
||||||
|
static bool is_valid_element_type(Type *ty);
|
||||||
|
|
||||||
|
static ArrayType *get(Type *contained, unsigned num_elements);
|
||||||
|
|
||||||
|
Type *get_element_type() const { return contained_; }
|
||||||
|
unsigned get_num_of_elements() const { return num_elements_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *contained_; // The element type of the array.
|
||||||
|
unsigned num_elements_; // Number of elements in the array.
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointerType : public Type {
|
||||||
|
public:
|
||||||
|
PointerType(Type *contained);
|
||||||
|
Type *get_element_type() const { return contained_; }
|
||||||
|
|
||||||
|
static PointerType *get(Type *contained);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *contained_; // The element type of the ptr.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_TYPE_H_
|
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef _SYSY_USER_H_
|
||||||
|
#define _SYSY_USER_H_
|
||||||
|
|
||||||
|
#include "Value.h"
|
||||||
|
#include <vector>
|
||||||
|
// #include <memory>
|
||||||
|
|
||||||
|
class User : public Value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
User(Type *ty, const std::string &name = "", unsigned num_ops = 0);
|
||||||
|
~User() = default;
|
||||||
|
|
||||||
|
std::vector<Value *>& get_operands();
|
||||||
|
|
||||||
|
// start from 0
|
||||||
|
Value *get_operand(unsigned i) const;
|
||||||
|
|
||||||
|
// start from 0
|
||||||
|
void set_operand(unsigned i, Value *v);
|
||||||
|
void add_operand( Value *v);
|
||||||
|
|
||||||
|
unsigned get_num_operand() const;
|
||||||
|
|
||||||
|
void remove_use_of_ops();
|
||||||
|
void remove_operands(int index1,int index2);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// std::unique_ptr< std::list<Value *> > operands_; // operands of this value
|
||||||
|
std::vector<Value *> operands_; // operands of this value
|
||||||
|
unsigned num_ops_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_USER_H_
|
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef _SYSY_VALUE_H_
|
||||||
|
#define _SYSY_VALUE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class Type;
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
struct Use
|
||||||
|
{
|
||||||
|
Value *val_;
|
||||||
|
unsigned arg_no_; // the no. of operand, e.g., func(a, b), a is 0, b is 1
|
||||||
|
Use(Value *val, unsigned no) : val_(val), arg_no_(no) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Value
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Value(Type *ty, const std::string &name = "");
|
||||||
|
~Value() = default;
|
||||||
|
|
||||||
|
Type *get_type() const { return type_; }
|
||||||
|
|
||||||
|
std::list<Use> &get_use_list() { return use_list_; }
|
||||||
|
|
||||||
|
void add_use(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(Value *new_val);
|
||||||
|
void remove_use(Value *val);
|
||||||
|
|
||||||
|
virtual std::string print() = 0;
|
||||||
|
private:
|
||||||
|
Type *type_;
|
||||||
|
std::list<Use> use_list_; // who use this value
|
||||||
|
std::string name_; // should we put name field here ?
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SYSY_VALUE_H_
|
@ -0,0 +1,30 @@
|
|||||||
|
#include<stdio.h>
|
||||||
|
/* Input & output functions */
|
||||||
|
int get_int(){int t; scanf("%d",&t); return t; }
|
||||||
|
int get_float(){float t; scanf("%f",&t); return t; }
|
||||||
|
int get_char(){char c; scanf("%c",&c); return (int)c; }
|
||||||
|
int get_int_array(int a[]){
|
||||||
|
int n;
|
||||||
|
scanf("%d",&n);
|
||||||
|
for(int i=0;i<n;i++)scanf("%d",&a[i]);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
int get_float_array(float a[]){
|
||||||
|
int n;
|
||||||
|
scanf("%d",&n);
|
||||||
|
for(int i=0;i<n;i++)scanf("%f",&a[i]);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
void put_int(int a){ printf("%d",a); }
|
||||||
|
void put_float(float a){ printf("%f",a); }
|
||||||
|
void put_char(int a){ printf("%c",a); }
|
||||||
|
void put_int_array(int n, int a[]){
|
||||||
|
printf("%d:",n);
|
||||||
|
for(int i=0;i<n;i++)printf(" %d",a[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
void put_float_array(int n, float a[]){
|
||||||
|
printf("%d:",n);
|
||||||
|
for(int i=0;i<n;i++)printf(" %f",a[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
# PW6 实验报告
|
||||||
|
|
||||||
|
学号1 姓名1 学号2 姓名2 学号3 姓名3
|
||||||
|
|
||||||
|
## 问题回答
|
||||||
|
|
||||||
|
请给出`SysYIR.md`中提到的两种getelementptr用法的区别, 并解释原因:
|
||||||
|
- `%2 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 %0`
|
||||||
|
- `%2 = getelementptr i32, i32* %1, i32 %0`
|
||||||
|
|
||||||
|
## 实验设计
|
||||||
|
|
||||||
|
## 实验难点及解决方案
|
||||||
|
|
||||||
|
## 实验总结
|
||||||
|
|
||||||
|
## 实验反馈
|
||||||
|
|
||||||
|
## 组间交流
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue