Commit ab890b55 authored by 李晓奇's avatar 李晓奇

36 points

parent 1b66a604
...@@ -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()`
## 实验设计 ## 实验设计
......
...@@ -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()) {
......
; 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment