编译原理:cminus_compiler-2021-fall Lab4

吐槽

第四次实验明明是中科大他们小组四周完成的作业,结果到某湖这里居然让我们一个人用两周的时间完成???有没有搞错啊歪歪歪!!!可能是老师知道我们自己写是不可能写出来的吧(X)
我在github上面看了差不多有五篇吧,然后有三篇就是直接用的中科大他们给出的官方答案,有一篇是自己写的但是运行不出来第十二个的结果,然后有一篇是自己写的可以运行全部的结果
然后我就基本上是在最后这个人的基础上修改出来了一个我自己的

0. 前言

本次实验和 Lab3 一样,需要使用 LightIR 框架自动产生 cminus-f 语言的LLVM IR。

经过 Lab3 的练手,相信大家已经掌握了 LightIR 的使用,并且对于 LLVM IR 也有了一定理解。在本次实验中,我们要使用访问者模式来实现 IR 自动生成。 对于产生的IR, 我们可以调用 clang 生成可执行文件,这样一个初级的 cminus-f 编译器就完成啦!

主要工作

1.阅读cminus-f 的语义规则成为语言律师 ,我们将按照语义实现程度进行评分
2.阅读LightIR 核心类介绍
3.阅读实验框架,理解如何使用框架以及注意事项
4.修改 src/cminusfc/cminusf_builder.cpp 来实现自动 IR 产生的算法,使得它能正确编译任何合法的 cminus-f 程序
5.在 report.md 中解释你们的设计,遇到的困难和解决方案

1. 实验框架

本次实验使用了由C++编写的 LightIR 来生成 LLVM IR。为了便于大家进行实验,该框架自动完成了语法树到 C++ 上的抽象语法树的转换。 我们可以使用访问者模式来设计抽象语法树 中的算法。大家可以参考打印抽象语法树的算法, 以及运行 test_ast 来理解访问者模式下算法的执行流程。

在include/cminusf_builder.hpp中,我还定义了一个用于存储作用域的类Scope。它的作用是辅助我们在遍历语法树时,管理不同作用域中的变量。它提供了以下接口:

// 进入一个新的作用域
void enter();
// 退出一个作用域
void exit();
// 往当前作用域插入新的名字->值映射
bool push(std::string name, Value *val);
// 根据名字,寻找到值
Value* find(std::string name);
// 判断当前是否在全局作用域内
bool in_global();

你们需要根据语义合理调用enter与exit,并且在变量声明和使用时正确调用push与find。在类CminusfBuilder中,有一个Scope类型的成员变量scope,它在初始化时已经将input、output等函数加入了作用域中。因此,你们在进行名字查找时不需要顾虑是否需要对特殊函数进行特殊操作。

2. 运行与调试

运行 cminusfc

mkdir build && cd build
cmake .. -DLLVM_DIR=/path/to/your/llvm/install/lib/cmake/llvm/
make -j
# 安装它以便于链接 libcminus_io.a
make install

编译后会产生 cminusfc 程序,它能将cminus文件输出为LLVM IR,也可以利用clang将IR编译成二进制。程序逻辑写在src/cminusfc/cminusfc.cpp中。

当需要对 .cminus 文件测试时,可以这样使用:

# 假设 cminusfc 的路径在你的$PATH中
# 利用构建好的 Module 生成 test.ll
# 注意,如果调用了外部函数,如 input, output 等,则无法使用lli运行
cminusfc test.cminus -emit-llvm

# 假设libcminus_io.a的路径在$LD_LIBRARY_PATH中,clang的路径在$PATH中
# 1. 利用构建好的 Module 生成 test.ll
# 2. 调用 clang 来编译 IR 并链接上静态链接库 libcminus_io.a,生成二进制文件 test
cminusfc test.cminus

自动测试

助教贴心地为大家准备了自动测试脚本,它在 tests/lab4 目录下,使用方法如下:

# 在 tests/lab4 目录下运行:
./lab4_test.py

如果完全正确,它会输出:

===========TEST START===========
Case 01:	Success
Case 02:	Success
Case 03:	Success
Case 04:	Success
Case 05:	Success
Case 06:	Success
Case 07:	Success
Case 08:	Success
Case 09:	Success
Case 10:	Success
Case 11:	Success
Case 12:	Success
============TEST END============

通过修改脚本,还可以方便地添加自定义测试用例

请注意助教提供的测试样例仅涵盖了最基础的测试情况,请自行设计测试样例进行测试。

logging

logging 是帮助大家打印调试信息的工具,如有需求可以阅读文档后进行使用

建议

1.比较你们编写的编译器产生的 IR 和 clang 产生的IR来找出可能的问题或发现新的思路
2.使用 logging 工具来打印调试信息
3.使用 GDB 等软件进行单步调试来检查错误的原因
4.合理分工

3. 提交要求

目录结构

.
├── CMakeLists.txt
├── Documentations
│   ├── ...
│   ├── common
│   |   ├── LightIR.md                  <- LightIR 相关文档
│   |   ├── logging.md                  <- logging 工具相关文档
│   |   └── cminusf.md                  <- cminus-f 的语法和语义文档
│   └── lab4
│       └── README.md                   <- lab4 实验文档说明(你在这里)
├── include                             <- 实验所需的头文件
│   ├── ...
│   ├── lightir/*
│   ├── cminusf_builder.hpp
|   └── ast.hpp
├── Reports
│   ├── ...
│   └── lab4
│       └── report.md                   <- lab4 所需提交的实验报告,请详细说明你们的设计(需要上交)
├── src
│   ├── ...
│   └── cminusfc
│       ├── cminusfc.cpp                <- cminusfc 的主程序文件
│       └── cminusf_builder.cpp         <- lab4 需要修改的文件,你们要在该文件中用访问者模式实现自动 IR 生成的算法(需要上交)
└── tests
    ├── ...
    └── lab4
        ├── testcases                   <- 助教提供的测试样例
        └── lab4_test.py                <- 助教提供的测试脚本

提交要求和评分标准

·提交要求
·实验部分:
·需要填补 ./src/cminusfc/cminusf_builder.cpp
·需要在 ./Reports/lab4/ 目录下撰写实验报告
·本次实验收取 ./src/cminusfc/cminusf_builder.cpp 文件和 ./Reports/lab4 目录

·评分标准:
·实验完成分(总分 60 分)组成如下:
·cminusf 程序测试 (45分)
·report.md(15分)
·禁止执行恶意代码,违者本次实验0分处理

代码

#include "cminusf_builder.hpp"
#include "logging.hpp"
// use these macros to get constant value
// 得到常数值的表示,方便后面多次用到
#define CONST_INT(num) \
    ConstantInt::get(num, module.get())

#define CONST_FP(num) \
    ConstantFP::get(num, module.get())
    
// You can define global variables here
// to store state
Value *ret;               //存储返回值
std::vector<Type *> Ints; //储存参数的类型,以确定函数的类型
int return_flag = 0;       //全局变量标识当前模块是否已经有return语句

/*
 * use CMinusfBuilder::Scope to construct scopes
 * scope.enter: enter a new scope
 * scope.exit: exit current scope
 * scope.push: add a new binding to current scope
 * scope.find: find and return the value bound to the name
 */

void CminusfBuilder::visit(ASTProgram &node) //遍历program下层的declaration-list中的声明
//program -> declaration-list
{
    for (auto decl : node.declarations)
    {
        decl->accept(*this);
    }
}

void CminusfBuilder::visit(ASTNum &node) //判断node的类型(整型或浮点型),将将相应的value值存入,并将地址赋给ret
{
    if(return_flag)
        return;
    if (node.type == TYPE_INT)
    {
        ret = CONST_INT(node.i_val);
    }
    else if (node.type == TYPE_FLOAT)
    {
        ret = CONST_FP(node.f_val);
    }
}

void CminusfBuilder::visit(ASTVarDeclaration &node) //变量声明
//var-declaration -> type-specifier ID ;type-specifier ID [INTEGER ]
{
    if(return_flag)
        return;
    auto TyInt32 = Type::get_int32_type(module.get());
    auto TyFloat = Type::get_float_type(module.get());
    
    if (!scope.in_global()) //局部
    {
        if (node.num != nullptr) //数组(指针非空
        {
            if(!node.num->i_val)
            {
            	Value * call_error = scope.find("neg_idx_except");//数组定义是大小为零时,打印报错信息
            	builder->create_call(call_error,{});
            }
            if (node.type == TYPE_INT) //整型数组
            {
                auto *arrayType = ArrayType::get(TyInt32, node.num->i_val);
                auto Local_IntArrayAlloca = builder->create_alloca(arrayType); //为数组分配空间
                scope.push(node.id, Local_IntArrayAlloca);
            }
            else if (node.type == TYPE_FLOAT) //浮点型数组
            {
                auto *arrayType = ArrayType::get(TyFloat, node.num->i_val);
                auto Local_FloatArrayAlloca = builder->create_alloca(arrayType); //为数组分配空间
                scope.push(node.id, Local_FloatArrayAlloca);
            }
        }
        else //变量
        {
            if (node.type == TYPE_INT) //整型变量
            {
                auto Local_IntAlloca = builder->create_alloca(TyInt32); //为变量分配空间
                scope.push(node.id, Local_IntAlloca);
            }
            else if (node.type == TYPE_FLOAT) //浮点型变量
            {
                auto Local_FloatAlloca = builder->create_alloca(TyFloat); //为变量分配空间
                scope.push(node.id, Local_FloatAlloca);
            }
        }
    }
    else //全局
    {
        if (node.num != nullptr ) //数组(指针非空
        {
            if(!node.num->i_val)
            {
            	Value * call_error = scope.find("neg_idx_except");
            	builder->create_call(call_error,{});
            }
            if (node.type == TYPE_INT) //整型数组
            {
                auto *arrayType = ArrayType::get(TyInt32, node.num->i_val);
                auto initializer = ConstantZero::get(arrayType, module.get());
                auto Globle_IntArrayAlloca = GlobalVariable::create(node.id, module.get(), arrayType, false, initializer); //为数组分配空间
                scope.push(node.id, Globle_IntArrayAlloca);
            }
            else if (node.type == TYPE_FLOAT) //浮点型数组
            {
                auto *arrayType = ArrayType::get(TyFloat, node.num->i_val);
                auto initializer = ConstantZero::get(arrayType, module.get()); //初始值赋为零
                auto Globle_FloatArrayAlloca = GlobalVariable::create(node.id, module.get(), arrayType, false, initializer); //为数组分配空间
                scope.push(node.id, Globle_FloatArrayAlloca);
            }
        }
        else //变量
        {
            if (node.type == TYPE_INT) //整型变量
            {
                auto initializer = ConstantZero::get(TyInt32, module.get());
                auto Globle_IntAlloca = GlobalVariable::create(node.id, module.get(), TyInt32, false, initializer); //为变量分配空间
                scope.push(node.id, Globle_IntAlloca);
            }
            else if (node.type == TYPE_FLOAT) //浮点型变量
            {
                auto initializer = ConstantZero::get(TyFloat, module.get());
                auto Globle_FloatAlloca = GlobalVariable::create(node.id, module.get(), TyFloat, false, initializer); //为变量分配空间
                scope.push(node.id, Globle_FloatAlloca);
            }
        }
    }
}

void CminusfBuilder::visit(ASTFunDeclaration &node) //函数声明
//fun-declaration → type-specifier ID ( params ) compound-stmt
{
    scope.enter(); //进入函数的作用域
    Type *TYPE32 = Type::get_int32_type(module.get());
    Type *TyFloat = Type::get_float_type(module.get());
    Type *TYPEV = Type::get_void_type(module.get());
    Type *TYPEARRAY_32 = PointerType::get_int32_ptr_type(module.get());
    Type *funType;

    Type *TYPEARRAY_INT_32 = PointerType::get_int32_ptr_type(module.get());
    Type *TYPEARRAY_FLOAT_32 = PointerType::get_float_ptr_type(module.get());

    //判断新声明的function的返回值类型
    if (node.type == TYPE_FLOAT)
        funType = TyFloat;
    else if(node.type == TYPE_VOID)
    {
        funType = TYPEV;
    }
    else
    {
    	funType = TYPE32;
    }

    // 函数参数的vector
    std::vector<Value *> args;
    if (node.params.size() > 0) //参数列表非空
    {
        for (auto param : node.params) //遍历Fundeclaration下的param节点,得到参数类型
        {
            param->accept(*this); //得到参数类型
        }
        auto fun = Function::create(FunctionType::get(funType, Ints), node.id, module.get()); //由函数类型定义函数
        auto bb = BasicBlock::create(module.get(), "entry", fun); // BB的名字在生成中无所谓,但是可以方便阅读
        builder->set_insert_point(bb);
        
        scope.exit(); //先退出当前作用域
        scope.push(node.id, fun); //函数名放进作用域
        scope.enter(); //再次进入函数的作用域
        
        for (auto param : node.params) //遍历Fundeclaration下的param节点,根据参数的类型分配空间
        {
            if (param->isarray) //数组
            {
                if (param->type == TYPE_INT) //整型数组
                {
                    auto pAlloca = builder->create_alloca(TYPEARRAY_INT_32); //在内存中分配空间
                    scope.push(param->id, pAlloca);
                }
                else if (param->type == TYPE_FLOAT)  //浮点型数组
                {
                    auto pAlloca = builder->create_alloca(TYPEARRAY_FLOAT_32);
                    scope.push(param->id, pAlloca);
                }

            }
            else if (param->type == TYPE_INT) //整型
            {
                auto pAlloca = builder->create_alloca(TYPE32);
                scope.push(param->id, pAlloca);
            }
            else if (param->type == TYPE_FLOAT) //浮点型
            {
                auto pAlloca = builder->create_alloca(TyFloat);
                scope.push(param->id, pAlloca);
            }
        }
        
        for (auto arg = fun->arg_begin(); arg != fun->arg_end(); arg++) //获取形参
        {
            args.push_back(*arg); // * 号运算符是从迭代器中取出迭代器当前指向的元素
        }
        int i = 0;
        for (auto param : node.params) //将参数store下来
        {
            auto pAlloca = scope.find(param->id);
            if (pAlloca == nullptr)
                exit(0);
            else
                builder->create_store(args[i++], pAlloca);
            Ints.pop_back(); //清空向量
        }
    }
    else //参数列表为空
    {
        auto fun = Function::create(FunctionType::get(funType, Ints), node.id, module.get()); //由函数类型定义函数
        auto bb = BasicBlock::create(module.get(), "entry", fun);// BB的名字在生成中无所谓,但是可以方便阅读
        builder->set_insert_point(bb);
        scope.exit(); //先退出当前作用域
        scope.push(node.id, fun); //函数名放进作用域
        scope.enter(); //再次进入函数的作用域
    }
    
    node.compound_stmt->accept(*this); //执行compound-stmt
    if(return_flag == 0) //当前模块没有return
    {
        auto return_type = builder->get_insert_block()->get_parent()->get_return_type();
        if(return_type->is_void_type())
            builder->create_void_ret();
        else if(return_type->is_integer_type())
            builder->create_ret(CONST_INT(0));
        else
            builder->create_ret(CONST_FP(0));
    }
    return_flag = 0;
    scope.exit();
}

void CminusfBuilder::visit(ASTParam &node) //对于每一个传进来的参数node,将其类型存入到全局变量Ints中 //参数
//param -> type-specifier ID | type-specifier ID []
{
    Type *TYPE32 = Type::get_int32_type(module.get());
    Type *TyFloat = Type::get_float_type(module.get());
    Type *TYPEARRAY_INT_32 = PointerType::get_int32_ptr_type(module.get());
    Type *TYPEARRAY_FLOAT_32 = PointerType::get_float_ptr_type(module.get());

    //返回参数类型并分配空间
    if (node.isarray) //数组参数
    {
        if (node.type == TYPE_INT)
        {
            Ints.push_back(TYPEARRAY_INT_32);
        }
        else if (node.type == TYPE_FLOAT)
        {
            Ints.push_back(TYPEARRAY_FLOAT_32);
        }
    }
    else if (node.type == TYPE_INT) //整型
    {
        Ints.push_back(TYPE32);
    }
    else if (node.type == TYPE_FLOAT) //浮点型
    {
        Ints.push_back(TyFloat);
    }
    return;
}

void CminusfBuilder::visit(ASTCompoundStmt &node) //复合语句
// compound-stmt -> { local-declarations statement-list }
{
    if(return_flag)
        return;
    scope.enter(); //先进入到新的作用域,可能有局部变量
    for (auto loc_decl : node.local_declarations) //遍历所有local_declarations
    {
        loc_decl->accept(*this);
    }
    for (auto stmt : node.statement_list) //遍历所有statement-list
    {
        stmt->accept(*this);
    }
    scope.exit();
}

void CminusfBuilder::visit(ASTExpressionStmt &node) //对expression结点调用accept //表达式语句
//expression-stmt→expression ;;
//expression→assign-expression ∣ simple-expression
{
    if(return_flag)
        return;
    if (node.expression != nullptr)
    {
        node.expression->accept(*this);
    }
}

void CminusfBuilder::visit(ASTSelectionStmt &node) //if
//selection-stmt→ ​if ( expression ) statement∣ if ( expression ) statement else statement​
{
    if(return_flag)
        return;
    Type *TYPE32 = Type::get_int32_type(module.get());
    node.expression->accept(*this);
    if (ret->get_type()->is_pointer_type()) //指针
        ret = builder->create_load(ret);
        
    if (ret->get_type()->is_float_type())
        ret = builder->create_fcmp_ne(ret, CONST_FP(0));
        
    else if (ret->get_type() == TYPE32)
        ret = builder->create_icmp_ne(ret, CONST_INT(0));
        
    //currentFunction
    auto currentFunc = builder->get_insert_block()->get_parent();
    auto trueBB = BasicBlock::create(module.get(), "", currentFunc); //创建true分支
    BasicBlock *falseBB;
    BasicBlock *nextBB;
    BranchInst *br;
    int insertedflag = 0;

    if (node.else_statement != nullptr) //else
    {
        falseBB = BasicBlock::create(module.get(), "", currentFunc);
        br = builder->create_cond_br(ret, trueBB, falseBB);
        //falseBB
        builder->set_insert_point(falseBB);
        node.else_statement->accept(*this);
        if (builder->get_insert_block()->get_terminator() == nullptr)
        { // no return inside the block
            insertedflag = 1;
            nextBB = BasicBlock::create(module.get(), "", currentFunc);
            builder->create_br(nextBB);
        }
        return_flag = 0;
        //tureBB
        builder->set_insert_point(trueBB);
        node.if_statement->accept(*this);
        if (builder->get_insert_block()->get_terminator() == nullptr)
        { // no return inside the block
            if (insertedflag == 0)
            {
                insertedflag = 1;
                nextBB = BasicBlock::create(module.get(), "", currentFunc);
            }
            builder->create_br(nextBB);
        }
        return_flag = !insertedflag;
        //nextBB
        if (insertedflag == 1)
        {
            builder->set_insert_point(nextBB);
        }
    }
    else //else
    {
        //tureBB
        nextBB = BasicBlock::create(module.get(), "", currentFunc);
        br = builder->create_cond_br(ret, trueBB, nextBB);
        builder->set_insert_point(trueBB);
        node.if_statement->accept(*this);
        if (return_flag == 0)
        {
            builder->create_br(nextBB);
        }
        return_flag = 0;

        //nextBB
        builder->set_insert_point(nextBB);
    }
}

void CminusfBuilder::visit(ASTIterationStmt &node)//迭代语句 while
//iteration-stmt→while ( expression ) statement
{
    if(return_flag)
        return;
    Type *TYPE32 = Type::get_int32_type(module.get());
    //currentFunction
    auto currentFunc = builder->get_insert_block()->get_parent();
    auto loopJudge = BasicBlock::create(module.get(), "", currentFunc);
    auto loopBody = BasicBlock::create(module.get(), "", currentFunc);
    auto out = BasicBlock::create(module.get(), "", currentFunc);
    if (builder->get_insert_block()->get_terminator() == nullptr)
        builder->create_br(loopJudge);

    //loopJudge BB
    builder->set_insert_point(loopJudge);
    node.expression->accept(*this);
    if (ret->get_type()->is_pointer_type())
        ret = builder->create_load(ret);
    if (ret->get_type()->is_float_type())
        ret = builder->create_fcmp_ne(ret, CONST_FP(0));
    else if (ret->get_type() == TYPE32)
        ret = builder->create_icmp_ne(ret, CONST_INT(0));
    auto br = builder->create_cond_br(ret, loopBody, out);

    //loopBody BB
    builder->set_insert_point(loopBody);
    node.statement->accept(*this);
    if (builder->get_insert_block()->get_terminator() == nullptr)
        builder->create_br(loopJudge);
    return_flag = 0;

    //outloop BB
    builder->set_insert_point(out);
}

void CminusfBuilder::visit(ASTReturnStmt &node) //return语句 //强制转换
//return-stmt→return ;return expression ;
{
    if(return_flag)
        return;
    Type *TYPE32 = Type::get_int32_type(module.get());
    Type *TYPE1 = Type::get_int1_type(module.get());
    Type *TyFloat = Type::get_float_type(module.get());
    auto return_type = builder->get_insert_block()->get_parent()->get_return_type();
    if (node.expression == nullptr) //空指针
    {
        if (!return_type->is_void_type())
            printf("return_type is not void, but expression is empty\n");
        builder->create_void_ret();
    }
    else
    {
        node.expression->accept(*this);
        if (return_type->is_void_type()) //void型
        {
            printf("return_type is void, but expression is not empty\n");
            builder->create_void_ret();
            return;
        }
        if (ret->get_type()->is_pointer_type()) //ret为指针型
            ret = builder->create_load(ret);
        if (return_type == TYPE32) //转化为int{
            if (ret->get_type() == TYPE1) //布尔型
                ret = builder->create_zext(ret, TYPE32);
            else if (ret->get_type() == TyFloat)
                ret = builder->create_fptosi(ret, TYPE32);
        }
        if (return_type == TyFloat) //转化为float{
            if (ret->get_type()->is_integer_type())
                ret = builder->create_sitofp(ret, TyFloat);
        }

        builder->create_ret(ret);
    }
    return_flag = 1;
}

void CminusfBuilder::visit(ASTVar &node) //变量
//var→ID ∣ ID [ expression]
{
    if(return_flag)
        return;
    Type *FloatPtrType = Type::get_float_ptr_type(module.get());
    Type *Int32PtrType = Type::get_int32_ptr_type(module.get());
    Type *TYPE32 = Type::get_int32_type(module.get());
    Type *TYPE1 = Type::get_int1_type(module.get());
    
    //currentFunction
    auto currentFunc = builder->get_insert_block()->get_parent();
    auto var = scope.find(node.id);
    if (var)
    {
        if (node.expression != nullptr) //数组
        {
            node.expression->accept(*this);
            Value *num = ret;
            //转化为int
            if (num->get_type()->is_pointer_type())
                num = builder->create_load(num);
            if (num->get_type() == TYPE1)
                num = builder->create_zext(num, TYPE32);
            else if (num->get_type()->is_float_type())
                num = builder->create_fptosi(num, TYPE32);
                
            //if num < 0; enter exphandBB
            auto exphandBB = BasicBlock::create(module.get(), "", currentFunc);
            auto normalBB = BasicBlock::create(module.get(), "", currentFunc);
            auto outBB = BasicBlock::create(module.get(), "", currentFunc);
            auto flagnum = builder->create_icmp_ge(num, CONST_INT(0));
            auto br = builder->create_cond_br(flagnum, normalBB, exphandBB);

            //normalBB
            builder->set_insert_point(normalBB);
            if (var->get_type()->get_pointer_element_type()->is_pointer_type())
            {
                //var is an array that sub func get from main func
                auto var_load = builder->create_load(var);
                var = builder->create_gep(var_load, {num});
            }
            else if (var->get_type()->get_pointer_element_type()->is_array_type())
            {
                //var is an id of array,get address of id[num]
                var = builder->create_gep(var, {CONST_INT(0), num});
            }
            else
            {
                printf("id is a float or int, but expression is not empty\n");
            }

            ret = var;
            builder->create_br(outBB);

            //exphandBB
            builder->set_insert_point(exphandBB);
            Value * call_error = scope.find("neg_idx_except");
            builder->create_call(call_error, {});
            builder->create_br(outBB);
            
            //outBB
            builder->set_insert_point(outBB);
        }
        
        else
        {
            if (!(var->get_type()->get_pointer_element_type()->is_float_type()) && !(var->get_type()->get_pointer_element_type()->is_integer_type()) && !(var->get_type()->get_pointer_element_type()->is_array_type()))
            {
                var = builder->create_load(var);
            }
            ret = var;
        }
    }
    else
    {
        printf("cannot find the var\n");
        return;
    }
}

void CminusfBuilder::visit(ASTAssignExpression &node) //赋值 //强制转换
//assign-expression→var = expression
{
    if(return_flag)
        return;
    Type *TYPE32 = Type::get_int32_type(module.get());
    Type *TYPE1 = Type::get_int1_type(module.get());
    Type *TYPEFLOAT = Type::get_float_type(module.get());
    node.var.get()->accept(*this);
    Value *var = ret;
    
    node.expression.get()->accept(*this);
    if (var->get_type()->get_pointer_element_type()->is_float_type()) //指向的是float{
        if (ret->get_type()->is_pointer_type())
            ret = builder->create_load(ret);
        if (ret->get_type()->is_integer_type())
            ret = builder->create_sitofp(ret, TYPEFLOAT);
        builder->create_store(ret, var);
    }
    else //指向的是int{
        if (ret->get_type()->is_pointer_type())
            ret = builder->create_load(ret);
        if (ret->get_type() == TYPE1)
            ret = builder->create_zext(ret, TYPE32);
        else if (ret->get_type()->is_float_type())
            ret = builder->create_fptosi(ret, TYPE32);
        builder->create_store(ret, var);
    }
}

void CminusfBuilder::visit(ASTSimpleExpression &node) //简单表达式
//simple-expression -> additive-expression relop additive- expression | additive-expression
{
    if(return_flag)
        return;
    Type *Int32Type = Type::get_int32_type(module.get());
    Type *FloatType = Type::get_float_type(module.get());
    Type *Int1Type = Type::get_int1_type(module.get());
    
    //simple-expression -> additive-expression
    if (!node.additive_expression_r) //简单加法表达式,通过accept调用下一层级
    {
        node.additive_expression_l->accept(*this);
    }
    
    //simple-expression -> additive-expression relop additive- expression
    else //关系表达式,运算结果为整型1 或者 0
    {
        //获取左值和右值
        Value *AdditiveLoad_l;
        Value *AdditiveLoad_r;
        Value *icmp;
        node.additive_expression_l->accept(*this);
        if (ret->get_type()->is_pointer_type())
            AdditiveLoad_l = builder->create_load(ret);
        else
            AdditiveLoad_l = ret;
        node.additive_expression_r->accept(*this);
        if (ret->get_type()->is_pointer_type())
            AdditiveLoad_r = builder->create_load(ret);
        else
            AdditiveLoad_r = ret;
            
        int flag = 0; //标志是否为浮点数
        
        if (AdditiveLoad_l->get_type()->is_float_type()) //l是浮点数
        {
            flag = 1;
            if (AdditiveLoad_r->get_type()->is_integer_type())
                AdditiveLoad_r = builder->create_sitofp(AdditiveLoad_r, FloatType);
        }
        else
        {
            if (AdditiveLoad_r->get_type()->is_float_type()) //r是浮点数
            {
                flag = 1;
                AdditiveLoad_l = builder->create_sitofp(AdditiveLoad_l, FloatType);
            }
            else
            {
                flag = 0;
                if (AdditiveLoad_l->get_type() == Int1Type)
                    AdditiveLoad_l = builder->create_zext(AdditiveLoad_l, Int32Type);
                if (AdditiveLoad_r->get_type() == Int1Type)
                    AdditiveLoad_r = builder->create_zext(AdditiveLoad_r, Int32Type);
            }
        }

        if (flag == 1) //float{
            switch (node.op)
            {
            case OP_GE:
                icmp = builder->create_fcmp_ge(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_GT:
                icmp = builder->create_fcmp_gt(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_LE:
                icmp = builder->create_fcmp_le(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_LT:
                icmp = builder->create_fcmp_lt(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_EQ:
                icmp = builder->create_fcmp_eq(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_NEQ:
                icmp = builder->create_fcmp_ne(AdditiveLoad_l, AdditiveLoad_r);
                break;
            default:
                break;
            }
        }
        
        else //int{
            switch (node.op)
            {
            case OP_GE:
                icmp = builder->create_icmp_ge(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_GT:
                icmp = builder->create_icmp_gt(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_LE:
                icmp = builder->create_icmp_le(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_LT:
                icmp = builder->create_icmp_lt(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_EQ:
                icmp = builder->create_icmp_eq(AdditiveLoad_l, AdditiveLoad_r);
                break;
            case OP_NEQ:
                icmp = builder->create_icmp_ne(AdditiveLoad_l, AdditiveLoad_r);
                break;
            default:
                break;
            }
        }
        ret = icmp;
    }
}

void CminusfBuilder::visit(ASTAdditiveExpression &node)
//additive-expression -> additive-expression addop term | term
{
    if(return_flag)
        return;
    Type *Int32Type = Type::get_int32_type(module.get());
    Type *Int1Type = Type::get_int1_type(module.get());
    Type *FloatType = Type::get_float_type(module.get());
    Value *AdditiveExpression;
    Value *Term;
    Value *icmp;
    
    //additive-expression -> term
    if (node.additive_expression == nullptr) //如果只是简单的项,转到下一层
    {
        node.term->accept(*this);
    }
    
    //additive-expression -> additive-expression addop term
    else
    {
        node.additive_expression->accept(*this);
        if (ret->get_type()->is_pointer_type())
            AdditiveExpression = builder->create_load(ret);
        else
            AdditiveExpression = ret;
        node.term->accept(*this);
        if (ret->get_type()->is_pointer_type())
            Term = builder->create_load(ret);
        else
            Term = ret;
        int flag = 0;
        
        if (AdditiveExpression->get_type()->is_float_type()) //如果是浮点数相加
        {
            flag = 1;
            if (Term->get_type()->is_integer_type())
                Term = builder->create_sitofp(Term, FloatType);
        }
        else
        {
            if (Term->get_type()->is_float_type()) //term为float{
                flag = 1;
                AdditiveExpression = builder->create_sitofp(AdditiveExpression, FloatType);
            }
            
            else
            {
                flag = 0;
                if (AdditiveExpression->get_type() == Int1Type)
                    AdditiveExpression = builder->create_zext(AdditiveExpression, Int32Type);
                if (Term->get_type() == Int1Type)
                    Term = builder->create_zext(Term, Int32Type);
            }
        }

        if (flag == 1) //float{
            if (node.op == OP_PLUS)
            {
                icmp = builder->create_fadd(AdditiveExpression, Term);
            }
            else
            {
                icmp = builder->create_fsub(AdditiveExpression, Term);
            }
        }
        
        else //int{
            if (node.op == OP_PLUS)
            {
                icmp = builder->create_iadd(AdditiveExpression, Term);
            }
            else
            {
                icmp = builder->create_isub(AdditiveExpression, Term);
            }
        }
        ret = icmp;
    }
}

void CminusfBuilder::visit(ASTTerm &node)
//term -> term mulop factor | factor
{
    if(return_flag)
        return;
    Type *Int32Type = Type::get_int32_type(module.get());
    Type *Int1Type = Type::get_int1_type(module.get());
    Type *FloatType = Type::get_float_type(module.get());
    Value *Term;
    Value *Factor;
    Value *icmp;
    
    //term -> factor
    if (!node.term)
    {
        node.factor->accept(*this);
    }
    
    //term -> term mulop factor
    else
    {
        node.term->accept(*this);
        if (ret->get_type()->is_pointer_type())
            Term = builder->create_load(ret);
        else
            Term = ret;
        node.factor->accept(*this);
        if (ret->get_type()->is_pointer_type())
            Factor = builder->create_load(ret);
        else
            Factor = ret;
        int flag = 0;
        if (Term->get_type()->is_float_type())
        {
            flag = 1;
            if (Factor->get_type()->is_integer_type())
                Factor = builder->create_sitofp(Factor, FloatType);
        }
        else
        {
            if (Factor->get_type()->is_float_type())
            {
                flag = 1;
                Term = builder->create_sitofp(Term, FloatType);
            }
            else
            {
                flag = 0;
                if (Factor->get_type() == Int1Type)
                    Factor = builder->create_zext(Factor, Int32Type);
                if (Term->get_type() == Int1Type)
                    Term = builder->create_zext(Term, Int32Type);
            }
        }

        if (flag == 1)
        {
            if (node.op == OP_MUL)
            {
                icmp = builder->create_fmul(Term, Factor);
            }
            else
            {
                icmp = builder->create_fdiv(Term, Factor);
            }
        }
        else
        {
            if (node.op == OP_MUL)
            {
                icmp = builder->create_imul(Term, Factor);
            }
            else
            {
                icmp = builder->create_isdiv(Term, Factor);
            }
        }
        ret = icmp;
    }
}

void CminusfBuilder::visit(ASTCall &node)
{
    //根据名字寻找到对应的值
    if(return_flag)
        return; 
    Value *value;
    value = scope.find(node.id); //调用scope.find()找ID对应的值
    
    if (value == nullptr) //是不是函数名
    {
        printf("cannot find the fun\n");
        return;
    }
        
    auto fun = value->get_type();
    if (!fun->is_function_type()) //检查函数类型
        return;
        
    auto callfun = static_cast<FunctionType *>(fun);
    Value *value_args;
    int i = 0;
    std::vector<Value *> function;
    Type *Int32Type = Type::get_int32_type(module.get());
    Type *FloatType = Type::get_float_type(module.get());
    Type *Int32PtrType = Type::get_int32_ptr_type(module.get());
    Type *Int1Type = Type::get_int1_type(module.get());
    
    
    for (auto Args : node.args) //检查参数类型是否匹配
    {
        auto arg_type = callfun->get_param_type(i);
        i++;
        Args->accept(*this);
        if (ret->get_type() == Int1Type) //如果ret是布尔型,ret先转换成32位整型
        {
            ret = builder->create_zext(ret, Int32Type);
        }
        if (arg_type == Int32Type) //要求的参数为整型
        {
            if (ret->get_type()->is_pointer_type())
                ret = builder->create_load(ret);
            else if (ret->get_type() == FloatType)
                ret = builder->create_fptosi(ret, Int32Type);
            value_args = ret;
        }
        else if (arg_type == FloatType) //要求的参数为浮点数
        {
            if (ret->get_type()->is_pointer_type())
                ret = builder->create_load(ret);
            else if (ret->get_type() == Int32Type)
                ret = builder->create_sitofp(ret, FloatType);
            value_args = ret;
        }
        else //要求的参数为指针
        {
            if (ret->get_type() == Int32Type || ret->get_type() == FloatType)
                return;
            value_args = ret;
        }
        function.push_back(value_args);
    }
    if (i != callfun->get_num_of_args())
    {
        printf("\t the num of arg error\n");
        return;
    }
    //call,get into sub func
    ret = builder->create_call(value, function);
}

思路

看注释!看注释!看注释!

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值