Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in
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
6
Merge Requests
6
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
06dd9b3d
You need to sign in or sign up before continuing.
Commit
06dd9b3d
authored
Oct 28, 2022
by
李晓奇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
97 points! I was afraid a huge change may lower the score hhhh..
parent
9e13604b
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
106 additions
and
26 deletions
+106
-26
Reports/3-ir-gen/report.md
Reports/3-ir-gen/report.md
+21
-7
src/cminusfc/cminusf_builder.cpp
src/cminusfc/cminusf_builder.cpp
+85
-19
No files found.
Reports/3-ir-gen/report.md
View file @
06dd9b3d
...
...
@@ -81,13 +81,27 @@ PB20111654 李晓奇
这个在访问
`ASTVar`
时解决掉:加入全局变量
`LV`
表式当前处理的是左值,所以要返回对应的地址,否则返回load出来的右值。
```
cpp
struct
ASTCall
:
ASTFactor
{
virtual
void
accept
(
ASTVisitor
&
)
override
final
;
std
::
string
id
;
std
::
vector
<
std
::
shared_ptr
<
ASTExpression
>>
args
;
};
```
LV为
`true`
时,对应的是赋值语句的左式、函数的指针引用。
另外嵌套递归调用可能导致LV发生变化,要注意。
> 关于函数传参的探讨
>
> - 值传递:由于LV是false,所以访问ASTVar的时候会load出来。可能需要类型转换。
>
> - 指针传递:设置LV是true,这时ASTVar会返回一个指针,**指向基本元素类型**(int|float)。
>
> 所以保证ASTVar返回的Value*变量符合要求,应该可以拿来直接使用,否则抛出异常。
-
针对ASTVar的探讨
-
LV:如果标记为true,则做左值,返回数据地址,否则返回提取出来的数据。
-
node.expression:如果非空,则有数组下标
-
Var的类型:这里断言是指针类型,所有push操作都应该维护这个性质。其指向的类型应该有三种:基本类型(int
\*
, float
\*
),数组类型([i32 x n]
\*
, [float x n]
\*
),二级指针类型(int
\*\*
, float
\*\*
)。
每种类型都有不同的对待逻辑,如何区分不同的Var类型呢?
-
全局变量要特殊对待
...
...
src/cminusfc/cminusf_builder.cpp
View file @
06dd9b3d
...
...
@@ -16,8 +16,9 @@
// definitions if you need to.
// the latest return value
bool
LV
=
false
;
Value
*
cur_value
=
nullptr
;
// if var is assignment's left part, LV is true
bool
LV
=
false
;
// function that is being built
Function
*
cur_fun
=
nullptr
;
...
...
@@ -265,10 +266,16 @@ void CminusfBuilder::visit(ASTParam &node) {
auto
param_value
=
cur_value
;
switch
(
node
.
type
)
{
case
TYPE_INT
:
{
if
(
node
.
isarray
)
cur_value
=
builder
->
create_alloca
(
INT32PTR_T
);
else
cur_value
=
builder
->
create_alloca
(
INT32_T
);
break
;
}
case
TYPE_FLOAT
:
{
if
(
node
.
isarray
)
cur_value
=
builder
->
create_alloca
(
FLOATPTR_T
);
else
cur_value
=
builder
->
create_alloca
(
FLOAT_T
);
break
;
}
...
...
@@ -403,20 +410,26 @@ void CminusfBuilder::visit(ASTVar &node) {
//!TODO: This function is empty now.
// Add some code here.
//
// Goal: calculate address
// 1. get base
// 2. get bias if there is, and cast it if needed.
bool
old_LV
=
LV
;
// First it's pointer type, the pointed elements have 3 cases:
// 1. int or float
// 2. [i32 x n] or [float x n]
// 3. int*
auto
memory
=
scope
.
find
(
node
.
id
);
Value
*
addr
;
if
(
memory
==
nullptr
)
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]*
assert
(
memory
->
get_type
()
->
is_pointer_type
());
auto
element_type
=
memory
->
get_type
()
->
get_pointer_element_type
();
if
(
node
.
expression
)
{
// e.g. int a[10]; // mem is [i32 x 10]*
bool
old_LV
=
LV
;
LV
=
false
;
node
.
expression
->
accept
(
*
this
);
LV
=
old_LV
;
// subscription type cast
if
(
not
Type
::
is_eq_type
(
cur_value
->
get_type
(),
INT32_T
))
{
if
(
Type
::
is_eq_type
(
cur_value
->
get_type
(),
FLOAT_T
))
cur_value
=
builder
->
create_fptosi
(
cur_value
,
INT32_T
);
...
...
@@ -436,15 +449,61 @@ void CminusfBuilder::visit(ASTVar &node) {
builder
->
set_insert_point
(
passBB
);
// Now the subscription is in cur_value, which is good value
// We should focus on the var type:
//
// assert it's pointer type
if
(
element_type
->
is_float_type
()
or
element_type
->
is_integer_type
())
{
// 1. int or float
error_exit
(
"invalid types for array subscript"
);
}
else
if
(
element_type
->
is_array_type
())
{
// 2. [i32 x n] or [float x n]
//
// addr is actually &memory[0][cur_value]
addr
=
builder
->
create_gep
(
memory
,
{
CONST_INT
(
0
),
cur_value
});
}
else
if
(
element_type
->
is_pointer_type
())
{
// 3. int*
// what to do:
// - int**->int*
// - seek addr
//
// addr is actually &(*memory)[cur_value]
addr
=
builder
->
create_load
(
memory
);
addr
=
builder
->
create_gep
(
addr
,
{
cur_value
});
}
// The logic for this part is the same as `int|float` without subscription.
// Cause we have subscription to find the particular element(int or float),
// we make `addr` its memory address.
}
else
{
// e.g. int a; // a is i32*
if
(
element_type
->
is_float_type
()
or
element_type
->
is_integer_type
())
{
// 1. int or float
// addr is the element's addr
addr
=
memory
;
}
LV
=
old_LV
;
}
else
{
if
(
LV
)
error_exit
(
"error: pointer or array type is not assignable"
);
// For array* or pointer* type, the right-value behaviour is quite special,
// so treat them apart.
if
(
element_type
->
is_array_type
())
{
// 2. [i32 x n] or [float x n]
// addr is the first element's address in the array
cur_value
=
builder
->
create_gep
(
memory
,
{
CONST_INT
(
0
),
CONST_INT
(
0
)});
}
else
if
(
element_type
->
is_pointer_type
())
{
// 3. int*
// addr is the content in the memory, which is actually pointer type
cur_value
=
builder
->
create_load
(
memory
);
}
return
;
}
}
if
(
LV
)
{
LOG_INFO
<<
"directly return addr"
<<
node
.
id
;
cur_value
=
addr
;
else
{
}
else
{
LOG_INFO
<<
"create load for var: "
<<
node
.
id
;
cur_value
=
builder
->
create_load
(
addr
);
}
}
...
...
@@ -624,11 +683,18 @@ void CminusfBuilder::visit(ASTCall &node) {
// type cast
if
(
not
Type
::
is_eq_type
(
param_type
,
cur_value
->
get_type
()))
{
if
(
param_type
->
is_pointer_type
())
{
if
(
not
Type
::
is_eq_type
(
param_type
->
get_pointer_element_type
(),
cur_value
->
get_type
()
->
get_array_element_type
()))
error_exit
(
"expected right pointer type"
);
// int[] to int* or float[] to flot*
cur_value
=
builder
->
create_gep
(
cur_value
,
{
CONST_INT
(
0
),
CONST_INT
(
0
)});
// shouldn't need type cast for pointer, logically
if
(
param_type
->
get_pointer_element_type
()
->
is_integer_type
()
or
param_type
->
get_pointer_element_type
()
->
is_float_type
())
error_exit
(
"BUG HERE: ASTVar return value is not int* or float*"
);
else
error_exit
(
"BUG HERE: function param needs weird pointer type"
);
/* if (not Type::is_eq_type(param_type->get_pointer_element_type(),
* cur_value->get_type()->get_pointer_element_type()->get_array_element_type()))
* error_exit("expected right pointer type");
* // int[] to int* or float[] to flot*
* cur_value = builder->create_gep(cur_value, {CONST_INT(0), CONST_INT(0)}); */
}
else
if
(
param_type
->
is_integer_type
()
or
param_type
->
is_float_type
())
{
// need type cast between int and float
if
(
not
cur_value
->
get_type
()
->
is_integer_type
()
and
not
cur_value
->
get_type
()
->
is_float_type
())
...
...
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