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
06dd9b3d
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
Hide 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,11 +266,17 @@ void CminusfBuilder::visit(ASTParam &node) {
auto
param_value
=
cur_value
;
switch
(
node
.
type
)
{
case
TYPE_INT
:
{
cur_value
=
builder
->
create_alloca
(
INT32_T
);
if
(
node
.
isarray
)
cur_value
=
builder
->
create_alloca
(
INT32PTR_T
);
else
cur_value
=
builder
->
create_alloca
(
INT32_T
);
break
;
}
case
TYPE_FLOAT
:
{
cur_value
=
builder
->
create_alloca
(
FLOAT_T
);
if
(
node
.
isarray
)
cur_value
=
builder
->
create_alloca
(
FLOATPTR_T
);
else
cur_value
=
builder
->
create_alloca
(
FLOAT_T
);
break
;
}
case
TYPE_VOID
:
...
...
@@ -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
;
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]*
assert
(
memory
->
get_type
()
->
is_pointer_type
())
;
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
);
addr
=
builder
->
create_gep
(
memory
,
{
CONST_INT
(
0
),
cur_value
});
// 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*
addr
=
memory
;
if
(
element_type
->
is_float_type
()
or
element_type
->
is_integer_type
())
{
// 1. int or float
// addr is the element's addr
addr
=
memory
;
}
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
;
}
}
LV
=
old_LV
;
if
(
LV
)
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