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
ab890b55
Commit
ab890b55
authored
Oct 27, 2022
by
李晓奇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
36 points
parent
1b66a604
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
115 additions
and
16 deletions
+115
-16
Reports/3-ir-gen/report.md
Reports/3-ir-gen/report.md
+28
-1
src/cminusfc/cminusf_builder.cpp
src/cminusfc/cminusf_builder.cpp
+68
-15
tests/3-ir-gen/testcases/lv1/assign_int_var_local.ll
tests/3-ir-gen/testcases/lv1/assign_int_var_local.ll
+19
-0
No files found.
Reports/3-ir-gen/report.md
View file @
ab890b55
...
@@ -66,9 +66,36 @@ PB20111654 李晓奇
...
@@ -66,9 +66,36 @@ PB20111654 李晓奇
6.
记录遇到的坑
6.
记录遇到的坑
-
形如这种产生式子
`term→term mulop factor ∣ factor`
,我为了图方便先求了
`factor`
,在根据
`term`
的有调用
`accept()`
,但是这样会导致左右操作数颠倒。
-
形如这种产生式子
`term→term mulop factor ∣ factor`
,我为了图方便先求了
`factor`
,在根据
`term`
的有调用
`accept()`
,但是这样会导致左右操作数颠倒。
-
我对于类型转换的控制比较严格,没考虑到的一率abort,因此很快发现了漏掉了bool类型的转换。
-
我对于类型转换的控制比较严格,没考虑到的一率abort,因此很快发现了漏掉了bool类型的转换。
-
接上条,一些类型转换的bug:
`i32`
到
`i1`
也是需要转换的,开始做的时候还没意识到这些(主要是没意识到
`i1`
的存在)。
-
接上条,一些类型转换的bug:
`i32`
到
`i1`
也是需要转换的,开始做的时候还没意识到这些(主要是没意识到
`i1`
的存在)。
-
接上条,关于
-
**核心问题**
:函数调用是值传递,比如
`f(a)`
,这里在中间代码看来,a返回的是一个指针,需要load出来再传过去。
但是对于字面量,又不需这样提取数据。可以使用
`dynamic_cast`
尝试解决。
但是出现了加减乘除时,这个又不能动态类型转换。
换句话说,访问
`ASTCall`
时,需要依次调用args的
`accept()`
,但是这个args!!!!expression应该返回的就是值才对。问题出现在变量的访问那里。
这个在访问
`ASTVar`
时解决掉:
-
如果做左值,返回指针元素
-
如果做右值,返回值
```
cpp
struct
ASTCall
:
ASTFactor
{
virtual
void
accept
(
ASTVisitor
&
)
override
final
;
std
::
string
id
;
std
::
vector
<
std
::
shared_ptr
<
ASTExpression
>>
args
;
};
```
-
全局变量要特殊对待
-
数组下标为负时要调用
`neg_idx_except()`
## 实验设计
## 实验设计
...
...
src/cminusfc/cminusf_builder.cpp
View file @
ab890b55
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
// definitions if you need to.
// definitions if you need to.
// the latest return value
// the latest return value
bool
LV
=
false
;
Value
*
cur_value
=
nullptr
;
Value
*
cur_value
=
nullptr
;
// function that is being built
// function that is being built
Function
*
cur_fun
=
nullptr
;
Function
*
cur_fun
=
nullptr
;
...
@@ -28,6 +29,10 @@ Type *INT32PTR_T;
...
@@ -28,6 +29,10 @@ Type *INT32PTR_T;
Type
*
FLOAT_T
;
Type
*
FLOAT_T
;
Type
*
FLOATPTR_T
;
Type
*
FLOATPTR_T
;
// initializer
ConstantZero
*
I32Initializer
;
ConstantZero
*
FloatInitializer
;
/*
/*
* use CMinusfBuilder::Scope to construct scopes
* use CMinusfBuilder::Scope to construct scopes
* scope.enter: enter a new scope
* scope.enter: enter a new scope
...
@@ -72,6 +77,8 @@ void CminusfBuilder::visit(ASTProgram &node) {
...
@@ -72,6 +77,8 @@ void CminusfBuilder::visit(ASTProgram &node) {
INT32PTR_T
=
Type
::
get_int32_ptr_type
(
module
.
get
());
INT32PTR_T
=
Type
::
get_int32_ptr_type
(
module
.
get
());
FLOAT_T
=
Type
::
get_float_type
(
module
.
get
());
FLOAT_T
=
Type
::
get_float_type
(
module
.
get
());
FLOATPTR_T
=
Type
::
get_float_ptr_type
(
module
.
get
());
FLOATPTR_T
=
Type
::
get_float_ptr_type
(
module
.
get
());
I32Initializer
=
ConstantZero
::
get
(
INT32_T
,
builder
->
get_module
());
FloatInitializer
=
ConstantZero
::
get
(
FLOAT_T
,
builder
->
get_module
());
for
(
auto
decl
:
node
.
declarations
)
{
for
(
auto
decl
:
node
.
declarations
)
{
decl
->
accept
(
*
this
);
decl
->
accept
(
*
this
);
...
@@ -99,29 +106,37 @@ void CminusfBuilder::visit(ASTNum &node) {
...
@@ -99,29 +106,37 @@ void CminusfBuilder::visit(ASTNum &node) {
void
CminusfBuilder
::
visit
(
ASTVarDeclaration
&
node
)
{
void
CminusfBuilder
::
visit
(
ASTVarDeclaration
&
node
)
{
//!TODO: This function is empty now.
//!TODO: This function is empty now.
// Add some code here.
// Add some code here.
bool
global
=
(
builder
->
get_insert_block
()
==
nullptr
);
if
(
node
.
num
)
{
if
(
node
.
num
)
{
// declares an array
// declares an array
//
//
// get array size
// get array size
node
.
num
->
accept
(
*
this
);
node
.
num
->
accept
(
*
this
);
//
//
// type cast
// !no type cast here!
if
(
Type
::
is_eq_type
(
cur_value
->
get_type
(),
FLOAT_T
))
if
(
not
(
node
.
num
->
type
==
TYPE_INT
))
cur_value
=
builder
->
create_fptosi
(
cur_value
,
INT32_T
);
error_exit
(
"size of array has non-integer type"
);
int
size
=
static_cast
<
ConstantInt
*>
(
cur_value
)
->
get_value
();
int
size
=
node
.
num
->
i_val
;
if
(
size
<=
0
)
if
(
size
<=
0
)
error_exit
(
"array size["
+
std
::
to_string
(
size
)
+
"] <= 0"
);
error_exit
(
"array size["
+
std
::
to_string
(
size
)
+
"] <= 0"
);
switch
(
node
.
type
)
{
switch
(
node
.
type
)
{
case
TYPE_INT
:
{
case
TYPE_INT
:
{
auto
I32Array_T
=
Type
::
get_array_type
(
INT32_T
,
size
);
auto
I32Array_T
=
Type
::
get_array_type
(
INT32_T
,
size
);
cur_value
=
builder
->
create_alloca
(
I32Array_T
);
if
(
global
)
GlobalVariable
::
create
(
node
.
id
,
builder
->
get_module
(),
I32Array_T
,
false
,
I32Initializer
);
else
builder
->
create_alloca
(
I32Array_T
);
break
;
break
;
}
}
case
TYPE_FLOAT
:
{
case
TYPE_FLOAT
:
{
auto
FloatArray_T
=
Type
::
get_array_type
(
FLOAT_T
,
size
);
auto
FloatArray_T
=
Type
::
get_array_type
(
FLOAT_T
,
size
);
cur_value
=
builder
->
create_alloca
(
FloatArray_T
);
if
(
global
)
GlobalVariable
::
create
(
node
.
id
,
builder
->
get_module
(),
FloatArray_T
,
false
,
FloatInitializer
);
else
builder
->
create_alloca
(
FloatArray_T
);
break
;
break
;
}
}
default:
default:
...
@@ -129,19 +144,29 @@ void CminusfBuilder::visit(ASTVarDeclaration &node) {
...
@@ -129,19 +144,29 @@ void CminusfBuilder::visit(ASTVarDeclaration &node) {
}
}
}
else
{
}
else
{
// flat int or float type
switch
(
node
.
type
)
{
switch
(
node
.
type
)
{
case
TYPE_INT
:
case
TYPE_INT
:
cur_value
=
builder
->
create_alloca
(
INT32_T
);
if
(
global
)
GlobalVariable
::
create
(
node
.
id
,
builder
->
get_module
(),
INT32_T
,
false
,
I32Initializer
);
else
builder
->
create_alloca
(
INT32_T
);
break
;
break
;
case
TYPE_FLOAT
:
case
TYPE_FLOAT
:
cur_value
=
builder
->
create_alloca
(
FLOAT_T
);
if
(
global
)
GlobalVariable
::
create
(
node
.
id
,
builder
->
get_module
(),
FLOAT_T
,
false
,
FloatInitializer
);
else
builder
->
create_alloca
(
INT32_T
);
break
;
break
;
default:
default:
error_exit
(
"Variable type(not array) is not int or float"
);
error_exit
(
"Variable type(not array) is not int or float"
);
}
}
}
}
if
(
not
scope
.
push
(
node
.
id
,
cur_value
))
if
(
not
scope
.
push
(
node
.
id
,
cur_value
))
error_exit
(
"variable redefined: "
+
node
.
id
);
error_exit
(
"variable redefined: "
+
node
.
id
);
LOG_DEBUG
<<
"add entry: "
<<
node
.
id
<<
" "
<<
cur_value
;
}
}
// Done
// Done
...
@@ -325,6 +350,8 @@ void CminusfBuilder::visit(ASTReturnStmt &node) {
...
@@ -325,6 +350,8 @@ void CminusfBuilder::visit(ASTReturnStmt &node) {
}
}
// Done
// Done
// if LV is marked, return memory addr
// else return value stored inside
void
CminusfBuilder
::
visit
(
ASTVar
&
node
)
{
void
CminusfBuilder
::
visit
(
ASTVar
&
node
)
{
//!TODO: This function is empty now.
//!TODO: This function is empty now.
// Add some code here.
// Add some code here.
...
@@ -337,6 +364,7 @@ void CminusfBuilder::visit(ASTVar &node) {
...
@@ -337,6 +364,7 @@ void CminusfBuilder::visit(ASTVar &node) {
Value
*
addr
;
Value
*
addr
;
if
(
memory
==
nullptr
)
if
(
memory
==
nullptr
)
error_exit
(
"variable "
+
node
.
id
+
" not declared"
);
error_exit
(
"variable "
+
node
.
id
+
" not declared"
);
LOG_DEBUG
<<
"find entry: "
<<
node
.
id
<<
" "
<<
memory
;
if
(
node
.
expression
)
{
// e.g. int a[10]; // mem is [i32 x 10]*
if
(
node
.
expression
)
{
// e.g. int a[10]; // mem is [i32 x 10]*
node
.
expression
->
accept
(
*
this
);
node
.
expression
->
accept
(
*
this
);
if
(
not
Type
::
is_eq_type
(
cur_value
->
get_type
(),
INT32_T
))
{
if
(
not
Type
::
is_eq_type
(
cur_value
->
get_type
(),
INT32_T
))
{
...
@@ -346,13 +374,27 @@ void CminusfBuilder::visit(ASTVar &node) {
...
@@ -346,13 +374,27 @@ void CminusfBuilder::visit(ASTVar &node) {
error_exit
(
"bad type for subscription"
);
error_exit
(
"bad type for subscription"
);
}
}
// now it's
auto
cond
=
builder
->
create_icmp_lt
(
cur_value
,
CONST_INT
(
0
));
auto
except_func
=
scope
.
find
(
"neg_idx_except"
);
auto
TBB
=
BasicBlock
::
create
(
builder
->
get_module
(),
"BadIdx"
,
cur_fun
);
auto
FBB
=
BasicBlock
::
create
(
builder
->
get_module
(),
"Pass"
,
cur_fun
);
builder
->
create_cond_br
(
cond
,
TBB
,
FBB
);
builder
->
set_insert_point
(
TBB
);
builder
->
create_call
(
except_func
,
{});
builder
->
set_insert_point
(
FBB
);
addr
=
builder
->
create_gep
(
memory
,
{
0
,
cur_value
});
addr
=
builder
->
create_gep
(
memory
,
{
0
,
cur_value
});
}
else
{
// e.g. int a; // a is i32*
}
else
{
// e.g. int a; // a is i32*
addr
=
memory
;
addr
=
memory
;
}
}
cur_value
=
addr
;
if
(
LV
)
cur_value
=
addr
;
else
{
cur_value
=
builder
->
create_load
(
addr
);
}
}
}
// Done
// Done
...
@@ -360,16 +402,18 @@ void CminusfBuilder::visit(ASTAssignExpression &node) {
...
@@ -360,16 +402,18 @@ void CminusfBuilder::visit(ASTAssignExpression &node) {
//!TODO: This function is empty now.
//!TODO: This function is empty now.
// Add some code here.
// Add some code here.
//
//
LV
=
true
;
node
.
var
->
accept
(
*
this
);
node
.
var
->
accept
(
*
this
);
auto
left
=
cur_value
;
LV
=
false
;
auto
addr
=
cur_value
;
node
.
expression
->
accept
(
*
this
);
node
.
expression
->
accept
(
*
this
);
assert
(
left
->
get_type
()
->
get_pointer_element_type
()
!=
nullptr
);
assert
(
addr
->
get_type
()
->
get_pointer_element_type
()
!=
nullptr
);
// type cast: left is a pointer type, pointed to i32 or float
// type cast: left is a pointer type, pointed to i32 or float
if
(
not
Type
::
is_eq_type
(
left
->
get_type
()
->
get_pointer_element_type
(),
cur_value
->
get_type
()))
{
if
(
not
Type
::
is_eq_type
(
addr
->
get_type
()
->
get_pointer_element_type
(),
cur_value
->
get_type
()))
{
if
(
cur_value
->
get_type
()
->
is_float_type
())
if
(
cur_value
->
get_type
()
->
is_float_type
())
cur_value
=
builder
->
create_fptosi
(
cur_value
,
INT32_T
);
cur_value
=
builder
->
create_fptosi
(
cur_value
,
INT32_T
);
else
if
(
left
->
get_type
()
->
get_pointer_element_type
()
->
is_float_type
())
else
if
(
addr
->
get_type
()
->
get_pointer_element_type
()
->
is_float_type
())
cur_value
=
builder
->
create_sitofp
(
cur_value
,
FLOAT_T
);
cur_value
=
builder
->
create_sitofp
(
cur_value
,
FLOAT_T
);
else
if
(
Type
::
is_eq_type
(
cur_value
->
get_type
(),
INT1_T
))
else
if
(
Type
::
is_eq_type
(
cur_value
->
get_type
(),
INT1_T
))
cur_value
=
builder
->
create_zext
(
cur_value
,
INT32_T
);
cur_value
=
builder
->
create_zext
(
cur_value
,
INT32_T
);
...
@@ -377,7 +421,7 @@ void CminusfBuilder::visit(ASTAssignExpression &node) {
...
@@ -377,7 +421,7 @@ void CminusfBuilder::visit(ASTAssignExpression &node) {
error_exit
(
"bad type for assignment"
);
error_exit
(
"bad type for assignment"
);
}
}
// gen code
// gen code
builder
->
create_store
(
left
,
cur_value
);
builder
->
create_store
(
addr
,
cur_value
);
}
}
// Done
// Done
...
@@ -522,10 +566,19 @@ void CminusfBuilder::visit(ASTCall &node) {
...
@@ -522,10 +566,19 @@ void CminusfBuilder::visit(ASTCall &node) {
if
(
node
.
args
.
size
()
!=
func
->
get_num_of_args
())
if
(
node
.
args
.
size
()
!=
func
->
get_num_of_args
())
error_exit
(
"expect "
+
std
::
to_string
(
func
->
get_num_of_args
())
+
" params, but "
+
error_exit
(
"expect "
+
std
::
to_string
(
func
->
get_num_of_args
())
+
" params, but "
+
std
::
to_string
(
node
.
args
.
size
())
+
" is given"
);
std
::
to_string
(
node
.
args
.
size
())
+
" is given"
);
// check every argument
for
(
int
i
=
0
;
i
!=
node
.
args
.
size
();
++
i
)
{
for
(
int
i
=
0
;
i
!=
node
.
args
.
size
();
++
i
)
{
// ith parameter's type
Type
*
param_type
=
func
->
get_function_type
()
->
get_param_type
(
i
);
Type
*
param_type
=
func
->
get_function_type
()
->
get_param_type
(
i
);
node
.
args
[
i
]
->
accept
(
*
this
);
node
.
args
[
i
]
->
accept
(
*
this
);
/* if (dynamic_cast<Constant *>(cur_value) != nullptr) {
* // this is literal
* cur_value = dynamic_cast<Constant *>(cur_value);
* } else {
* // this is variable
* cur_value = builder->create_load(cur_value);
* } */
// type cast
// type cast
if
(
not
Type
::
is_eq_type
(
param_type
,
cur_value
->
get_type
()))
{
if
(
not
Type
::
is_eq_type
(
param_type
,
cur_value
->
get_type
()))
{
if
(
param_type
->
is_pointer_type
())
{
if
(
param_type
->
is_pointer_type
())
{
...
...
tests/3-ir-gen/testcases/lv1/assign_int_var_local.ll
0 → 100644
View file @
ab890b55
; ModuleID = 'cminus'
source_filename
=
"assign_int_var_local.cminus"
declare
i32
@input
()
declare
void
@output
(
i32
)
declare
void
@outputFloat
(
float
)
declare
void
@neg_idx_except
()
define
void
@main
()
{
label_entry:
%op0
=
alloca
i32
store
i32
*
%op0
,
i32
1234
%op1
=
load
i32
,
i32
*
%op0
call
void
@output
(
i32
%op1
)
ret
void
}
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