Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
2
2022fall-Compiler_CMinus
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李晓奇
2022fall-Compiler_CMinus
Commits
24af41cc
Commit
24af41cc
authored
Oct 15, 2022
by
李晓奇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finish part3: visitor pattern and the report.
parent
4b7accb1
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
157 additions
and
85 deletions
+157
-85
Reports/.gitignore
Reports/.gitignore
+1
-0
Reports/2-ir-gen-warmup/figures/CALC_AST.png
Reports/2-ir-gen-warmup/figures/CALC_AST.png
+0
-0
Reports/2-ir-gen-warmup/figures/assign.png
Reports/2-ir-gen-warmup/figures/assign.png
+0
-0
Reports/2-ir-gen-warmup/figures/fun.png
Reports/2-ir-gen-warmup/figures/fun.png
+0
-0
Reports/2-ir-gen-warmup/figures/if.png
Reports/2-ir-gen-warmup/figures/if.png
+0
-0
Reports/2-ir-gen-warmup/figures/while.png
Reports/2-ir-gen-warmup/figures/while.png
+0
-0
Reports/2-ir-gen-warmup/report.md
Reports/2-ir-gen-warmup/report.md
+69
-8
tests/2-ir-gen-warmup/calculator/calc.cpp
tests/2-ir-gen-warmup/calculator/calc.cpp
+12
-10
tests/2-ir-gen-warmup/calculator/calc_ast.hpp
tests/2-ir-gen-warmup/calculator/calc_ast.hpp
+39
-30
tests/2-ir-gen-warmup/calculator/calc_builder.cpp
tests/2-ir-gen-warmup/calculator/calc_builder.cpp
+27
-30
tests/2-ir-gen-warmup/calculator/calc_builder.hpp
tests/2-ir-gen-warmup/calculator/calc_builder.hpp
+8
-6
tests/2-ir-gen-warmup/stu_cpp/fun_generator.cpp
tests/2-ir-gen-warmup/stu_cpp/fun_generator.cpp
+1
-1
No files found.
Reports/.gitignore
View file @
24af41cc
1-parser/*.pdf
2-ir-gen-warmup/*.pdf
Reports/2-ir-gen-warmup/figures/CALC_AST.png
0 → 100644
View file @
24af41cc
1.5 MB
Reports/2-ir-gen-warmup/figures/assign.png
0 → 100644
View file @
24af41cc
2.6 MB
Reports/2-ir-gen-warmup/figures/fun.png
0 → 100644
View file @
24af41cc
2 MB
Reports/2-ir-gen-warmup/figures/if.png
0 → 100644
View file @
24af41cc
2.66 MB
Reports/2-ir-gen-warmup/figures/while.png
0 → 100644
View file @
24af41cc
2.99 MB
Reports/2-ir-gen-warmup/report.md
View file @
24af41cc
# lab2 实验报告
学号 姓名
PB20111654 李晓奇
## 问题1: getelementptr
请给出
`IR.md`
中提到的两种 getelementptr 用法的区别,并稍加解释:
-
`%2 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 %0`
-
`%2 = getelementptr i32, i32* %1 i32 %0`
-
`%2 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 %0`
%2是
`i32*`
类型。
我的理解是,这条指令相当于
`%2=&%1[0][%0]`
,其中将
`%1`
看成指向至少有两层结构的指针,GEP指令最后边的两个数字一是用来指定进入的层数,一是用来指定每层的偏移量。
第一个
`i32 0`
表示指向第一个
`[10 x i32]`
块
第二个
`i32 %0`
表示在第一个
`[10 x i32]`
块中指向第
`%0`
个元素
GEP指令返回这个元素的指针,赋值给%2
-
`%2 = getelementptr i32, i32* %1 i32 %0`
%2同样是
`i32*`
类型。
%1是指针,不同于上式(%1指向数组),本式%1指向
`i32`
类型,所以填入一个偏移数字,即GEP指令返回
`%1[%0]`
的指针,赋值给%2。
## 问题2: cpp 与 .ll 的对应
请说明你的 cpp 代码片段和 .ll 的每个 BasicBlock 的对应关系。
### assign.c

### fun.c

### if.c

### while.c

## 问题3: Visitor Pattern
分析
`calc`
程序在输入为
`4 * (8 + 4 - 1) / 2`
时的行为:
分析
`calc`
程序在输入为
`4 * (8 + 4 - 1) / 2`
时的行为:
1.
请画出该表达式对应的抽象语法树(使用
`calc_ast.hpp`
中的
`CalcAST*`
类型和在该类型中存储的值来表示),并给节点使用数字编号。
2.
请指出示例代码在用访问者模式遍历该语法树时的遍历顺序。
AST如下,略去了CalcAST中的root:
!
[](
figures/CALC_AST.png
)
序列请按如下格式指明(序号为问题 2.1 中的编号):
3->2->5->1
2.
请指出示例代码在用访问者模式遍历该语法树时的遍历顺序。
CalcBuilder类从AST的树根开始,访问每个节点,具体行为如下:
-
如果节点是中间节点,则visit会触发该节点内部的每一个子节点的accept函数,经过一次或多次调用又触发CalcBuilder的visit,所以进行递归。
-
如果节点是叶子节点,即CalcASTNum类型,则可以直接读出这个节点的数值,保存在CalcBuilder类中的val中,回溯时会使用到。
所以CalcBuilder访问AST是个深度优先递归遍历的过程。
遍历顺序是:
1->2->3->4->5->7->8->9->11->14->16->12->15->10->13->6
> 个人感觉这个过程像是根据分析树构建语法树。过程中通过val保存一次visit调用的结果,只有在涉及到翻译的节点,即加减乘除运算时才做输出。
## 实验难点
描述在实验中遇到的问题、分析和解决方案。
-
理解GEP指令和指针的关系:阅读
[
资料
](
https://llvm.org/docs/GetElementPtr.html#what-effect-do-address-spaces-have-on-geps
)
。
-
lightIR API的使用方法:相比
[
代码
](
http://202.38.79.174/compiler_staff/2022fall-compiler_cminus/-/tree/master/include/lightir
)
,
[
文档
](
http://202.38.79.174/compiler_staff/2022fall-compiler_cminus/-/blob/master/Documentations/common/LightIR.md#c-apis
)
中有更多有助于理解的信息。所以先扫一遍文档获得宏观上的理解,再读
[
示例
](
http://202.38.79.174/compiler_staff/2022fall-compiler_cminus/-/blob/master/tests/2-ir-gen-warmup/ta_gcd/gcd_array_generator.cpp
)
。对于API中的每个类,文档和代码配合着看,大致就能理解了。
-
理解CalcAST和CalcBuilder的行为:读一遍代码就能懂了。
## 实验反馈
吐槽?建议?
暂无~
tests/2-ir-gen-warmup/calculator/calc.cpp
View file @
24af41cc
extern
"C"
{
#include "syntax_tree.h"
extern
syntax_tree
*
parse
(
const
char
*
);
#include "syntax_tree.h"
extern
syntax_tree
*
parse
(
const
char
*
);
}
#include <cstdio>
#include <fstream>
...
...
@@ -10,8 +10,8 @@ using namespace std::literals::string_literals;
int
main
(
int
argc
,
char
*
argv
[])
{
syntax_tree
*
tree
=
NULL
;
const
char
*
input
=
NULL
;
syntax_tree
*
tree
=
NULL
;
const
char
*
input
=
NULL
;
if
(
argc
>=
3
)
{
printf
(
"usage: %s
\n
"
,
argv
[
0
]);
...
...
@@ -22,22 +22,24 @@ int main(int argc, char *argv[])
if
(
argc
==
2
)
{
input
=
argv
[
1
];
}
else
{
printf
(
"Input an arithmatic expression (press Ctrl+D in a new line after you finish the expression):
\n
"
);
printf
(
"Input an arithmatic expression (press Ctrl+D in a new line "
"after you finish the expression):
\n
"
);
}
tree
=
parse
(
input
);
CalcAST
ast
(
tree
);
CalcAST
ast
(
tree
);
CalcBuilder
builder
;
auto
module
=
builder
.
build
(
ast
);
auto
IR
=
module
->
print
();
auto
module
=
builder
.
build
(
ast
);
auto
IR
=
module
->
print
();
std
::
ofstream
output_stream
;
auto
output_file
=
"result.ll"
;
auto
output_file
=
"result.ll"
;
output_stream
.
open
(
output_file
,
std
::
ios
::
out
);
output_stream
<<
"; ModuleID = 'calculator'
\n
"
;
output_stream
<<
IR
;
output_stream
.
close
();
auto
command_string
=
"clang -O0 -w "
s
+
"result.ll -o result -L. -lcminus_io"
;
auto
command_string
=
"clang -O0 -w "
s
+
"result.ll -o result -L. -lcminus_io"
;
auto
ret
=
std
::
system
(
command_string
.
c_str
());
if
(
ret
)
{
printf
(
"something went wrong!
\n
"
);
...
...
tests/2-ir-gen-warmup/calculator/calc_ast.hpp
View file @
24af41cc
#ifndef _CALC_AST_HPP_
#define _CALC_AST_HPP_
extern
"C"
{
#include "syntax_tree.h"
extern
syntax_tree
*
parse
(
const
char
*
input
);
#include "syntax_tree.h"
extern
syntax_tree
*
parse
(
const
char
*
input
);
}
#include <vector>
#include <memory>
...
...
@@ -32,59 +32,68 @@ struct CalcASTFactor;
class
CalcASTVisitor
;
class
CalcAST
{
public:
class
CalcAST
{
public:
CalcAST
()
=
delete
;
CalcAST
(
syntax_tree
*
);
CalcAST
(
CalcAST
&&
tree
)
{
root
=
tree
.
root
;
CalcAST
(
CalcAST
&&
tree
)
{
root
=
tree
.
root
;
tree
.
root
=
nullptr
;
};
CalcASTInput
*
get_root
()
{
return
root
.
get
();
}
void
run_visitor
(
CalcASTVisitor
&
visitor
);
private:
CalcASTNode
*
transform_node_iter
(
syntax_tree_node
*
);
CalcASTInput
*
get_root
()
{
return
root
.
get
();
}
void
run_visitor
(
CalcASTVisitor
&
visitor
);
private:
CalcASTNode
*
transform_node_iter
(
syntax_tree_node
*
);
std
::
shared_ptr
<
CalcASTInput
>
root
=
nullptr
;
};
struct
CalcASTNode
{
struct
CalcASTNode
{
virtual
void
accept
(
CalcASTVisitor
&
)
=
0
;
};
struct
CalcASTInput
:
CalcASTNode
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
struct
CalcASTInput
:
CalcASTNode
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
std
::
shared_ptr
<
CalcASTExpression
>
expression
;
};
struct
CalcASTFactor
:
CalcASTNode
{
struct
CalcASTFactor
:
CalcASTNode
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
;
};
struct
CalcASTNum
:
CalcASTFactor
{
struct
CalcASTNum
:
CalcASTFactor
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
int
val
;
int
val
;
};
struct
CalcASTExpression
:
CalcASTFactor
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
struct
CalcASTExpression
:
CalcASTFactor
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
std
::
shared_ptr
<
CalcASTExpression
>
expression
;
AddOp
op
;
std
::
shared_ptr
<
CalcASTTerm
>
term
;
AddOp
op
;
std
::
shared_ptr
<
CalcASTTerm
>
term
;
};
struct
CalcASTTerm
:
CalcASTNode
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
std
::
shared_ptr
<
CalcASTTerm
>
term
;
MulOp
op
;
struct
CalcASTTerm
:
CalcASTNode
{
virtual
void
accept
(
CalcASTVisitor
&
)
override
final
;
std
::
shared_ptr
<
CalcASTTerm
>
term
;
MulOp
op
;
std
::
shared_ptr
<
CalcASTFactor
>
factor
;
};
class
CalcASTVisitor
{
public:
virtual
void
visit
(
CalcASTInput
&
)
=
0
;
virtual
void
visit
(
CalcASTNum
&
)
=
0
;
class
CalcASTVisitor
{
public:
virtual
void
visit
(
CalcASTInput
&
)
=
0
;
virtual
void
visit
(
CalcASTNum
&
)
=
0
;
virtual
void
visit
(
CalcASTExpression
&
)
=
0
;
virtual
void
visit
(
CalcASTTerm
&
)
=
0
;
virtual
void
visit
(
CalcASTTerm
&
)
=
0
;
};
#endif
tests/2-ir-gen-warmup/calculator/calc_builder.cpp
View file @
24af41cc
#include "calc_builder.hpp"
std
::
unique_ptr
<
Module
>
CalcBuilder
::
build
(
CalcAST
&
ast
)
{
module
=
std
::
unique_ptr
<
Module
>
(
new
Module
(
"Cminus code"
));
builder
=
new
IRBuilder
(
nullptr
,
module
.
get
());
std
::
unique_ptr
<
Module
>
CalcBuilder
::
build
(
CalcAST
&
ast
)
{
module
=
std
::
unique_ptr
<
Module
>
(
new
Module
(
"Cminus code"
));
builder
=
new
IRBuilder
(
nullptr
,
module
.
get
());
auto
TyVoid
=
Type
::
get_void_type
(
module
.
get
());
TyInt32
=
Type
::
get_int32_type
(
module
.
get
());
TyInt32
=
Type
::
get_int32_type
(
module
.
get
());
std
::
vector
<
Type
*>
output_params
;
output_params
.
push_back
(
TyInt32
);
auto
output_type
=
FunctionType
::
get
(
TyVoid
,
output_params
);
auto
output_fun
=
Function
::
create
(
output_type
,
"output"
,
module
.
get
());
auto
main
=
Function
::
create
(
FunctionType
::
get
(
TyInt32
,
{}),
"main"
,
module
.
get
());
auto
output_fun
=
Function
::
create
(
output_type
,
"output"
,
module
.
get
());
auto
main
=
Function
::
create
(
FunctionType
::
get
(
TyInt32
,
{}),
"main"
,
module
.
get
());
auto
bb
=
BasicBlock
::
create
(
module
.
get
(),
"entry"
,
main
);
builder
->
set_insert_point
(
bb
);
ast
.
run_visitor
(
*
this
);
...
...
@@ -23,10 +19,9 @@ CalcBuilder::build(CalcAST &ast) {
builder
->
create_ret
(
ConstantInt
::
get
(
0
,
module
.
get
()));
return
std
::
move
(
module
);
}
void
CalcBuilder
::
visit
(
CalcASTInput
&
node
)
{
node
.
expression
->
accept
(
*
this
);
}
void
CalcBuilder
::
visit
(
CalcASTExpression
&
node
)
{
void
CalcBuilder
::
visit
(
CalcASTInput
&
node
)
{
node
.
expression
->
accept
(
*
this
);
}
void
CalcBuilder
::
visit
(
CalcASTExpression
&
node
)
{
if
(
node
.
expression
==
nullptr
)
{
node
.
term
->
accept
(
*
this
);
}
else
{
...
...
@@ -35,17 +30,18 @@ void CalcBuilder::visit(CalcASTExpression &node) {
node
.
term
->
accept
(
*
this
);
auto
r_val
=
val
;
switch
(
node
.
op
)
{
case
OP_PLUS
:
val
=
builder
->
create_iadd
(
l_val
,
r_val
);
break
;
case
OP_MINUS
:
val
=
builder
->
create_isub
(
l_val
,
r_val
);
break
;
case
OP_PLUS
:
val
=
builder
->
create_iadd
(
l_val
,
r_val
);
break
;
case
OP_MINUS
:
val
=
builder
->
create_isub
(
l_val
,
r_val
);
break
;
}
}
}
void
CalcBuilder
::
visit
(
CalcASTTerm
&
node
)
{
void
CalcBuilder
::
visit
(
CalcASTTerm
&
node
)
{
if
(
node
.
term
==
nullptr
)
{
node
.
factor
->
accept
(
*
this
);
}
else
{
...
...
@@ -54,16 +50,17 @@ void CalcBuilder::visit(CalcASTTerm &node) {
node
.
factor
->
accept
(
*
this
);
auto
r_val
=
val
;
switch
(
node
.
op
)
{
case
OP_MUL
:
val
=
builder
->
create_imul
(
l_val
,
r_val
);
break
;
case
OP_DIV
:
val
=
builder
->
create_isdiv
(
l_val
,
r_val
);
break
;
case
OP_MUL
:
val
=
builder
->
create_imul
(
l_val
,
r_val
);
break
;
case
OP_DIV
:
val
=
builder
->
create_isdiv
(
l_val
,
r_val
);
break
;
}
}
}
void
CalcBuilder
::
visit
(
CalcASTNum
&
node
)
{
void
CalcBuilder
::
visit
(
CalcASTNum
&
node
)
{
val
=
ConstantInt
::
get
(
node
.
val
,
module
.
get
());
}
tests/2-ir-gen-warmup/calculator/calc_builder.hpp
View file @
24af41cc
...
...
@@ -7,18 +7,20 @@
#include "Module.h"
#include "Type.h"
#include "calc_ast.hpp"
class
CalcBuilder
:
public
CalcASTVisitor
{
public:
class
CalcBuilder
:
public
CalcASTVisitor
{
public:
std
::
unique_ptr
<
Module
>
build
(
CalcAST
&
ast
);
private:
private:
virtual
void
visit
(
CalcASTInput
&
)
override
final
;
virtual
void
visit
(
CalcASTNum
&
)
override
final
;
virtual
void
visit
(
CalcASTExpression
&
)
override
final
;
virtual
void
visit
(
CalcASTTerm
&
)
override
final
;
IRBuilder
*
builder
;
Value
*
val
;
Type
*
TyInt32
;
IRBuilder
*
builder
;
Value
*
val
;
Type
*
TyInt32
;
std
::
unique_ptr
<
Module
>
module
;
};
#endif
tests/2-ir-gen-warmup/stu_cpp/fun_generator.cpp
View file @
24af41cc
...
...
@@ -10,7 +10,7 @@
int
main
()
{
auto
mod
=
new
Module
(
"
Cminus code"
);
// module name是什么无关紧要
auto
mod
=
new
Module
(
"
fun.cpp"
);
auto
bud
=
new
IRBuilder
(
nullptr
,
mod
);
Type
*
I32Type
=
Type
::
get_int32_type
(
mod
);
std
::
vector
<
Type
*>
OneIntArg
(
1
,
I32Type
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment