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