更新目录结构,修改IR结构,部分修复IR生成
This commit is contained in:
86
TODO.md
Normal file
86
TODO.md
Normal file
@@ -0,0 +1,86 @@
|
||||
要打通从SysY到RISC-V的完整编译流程,以下是必须实现的核心模块和关键步骤(按编译流程顺序)。在你们当前IR生成阶段,可以优先实现这些基础模块来快速获得可工作的RISC-V汇编输出:
|
||||
|
||||
### 1. **前端必须模块**
|
||||
- **词法/语法分析**(已完成):
|
||||
- `SysYLexer`/`SysYParser`:ANTLR生成的解析器
|
||||
- **IR生成核心**:
|
||||
- `SysYIRGenerator`:将AST转换为中间表示(IR)
|
||||
- `IRBuilder`:构建指令和基本块的工具类(你们正在实现的部分)
|
||||
|
||||
### 2. **中端必要优化(最小集合)**
|
||||
| 优化阶段 | 关键作用 | 是否必须 |
|
||||
|-------------------|----------------------------------|----------|
|
||||
| `Mem2Reg` | 消除冗余内存访问,转换为SSA形式 | ✅ 核心 |
|
||||
| `DCE` (死代码消除) | 移除无用指令 | ✅ 必要 |
|
||||
| `DFE` (死函数消除) | 移除未使用的函数 | ✅ 必要 |
|
||||
| `FuncAnalysis` | 函数调用关系分析 | ✅ 基础 |
|
||||
| `Global2Local` | 全局变量降级为局部变量 | ✅ 重要 |
|
||||
|
||||
### 3. **后端核心流程(必须实现)**
|
||||
```mermaid
|
||||
graph LR
|
||||
A[IR指令选择] --> B[寄存器分配]
|
||||
B --> C[指令调度]
|
||||
C --> D[汇编生成]
|
||||
```
|
||||
|
||||
1. **指令选择**(关键步骤):
|
||||
- `DAGBuilder`:将IR转换为有向无环图(DAG)
|
||||
- `DAGCoverage`:DAG到目标指令的映射
|
||||
- `Mid2End`:IR到机器指令的转换接口
|
||||
|
||||
2. **寄存器分配**:
|
||||
- `RegisterAlloc`:基础寄存器分配器(可先实现简单算法如线性扫描)
|
||||
|
||||
3. **汇编生成**:
|
||||
- `RiscvPrinter`:将机器指令输出为RISC-V汇编
|
||||
- 实现基础指令集:`add`/`sub`/`lw`/`sw`/`beq`/`jal`等
|
||||
|
||||
### 4. **最小可工作流程**
|
||||
```cpp
|
||||
// 精简版编译流程(跳过复杂优化)
|
||||
int main() {
|
||||
// 1. 前端解析
|
||||
auto module = sysy::SysYIRGenerator().genIR(input);
|
||||
|
||||
// 2. 关键中端优化
|
||||
sysy::Mem2Reg(module).run(); // 必须
|
||||
sysy::Global2Local(module).run(); // 必须
|
||||
sysy::DCE(module).run(); // 推荐
|
||||
|
||||
// 3. 后端代码生成
|
||||
auto backendModule = mid2end::CodeGenerater().run(module);
|
||||
riscv::RiscvPrinter().print("output.s", backendModule);
|
||||
}
|
||||
```
|
||||
|
||||
### 5. **当前开发优先级建议**
|
||||
1. **完成IR生成**:
|
||||
- 确保能构建基本块、函数、算术/内存/控制流指令
|
||||
- 实现`createCall`/`createLoad`/`createStore`等核心方法
|
||||
|
||||
2. **实现Mem2Reg**:
|
||||
- 插入Phi节点
|
||||
- 变量重命名(关键算法)
|
||||
|
||||
3. **构建基础后端**:
|
||||
- 指令选择:实现IR到RISC-V的简单映射(例如:`IRAdd` → `add`)
|
||||
- 寄存器分配:使用无限寄存器方案(后期替换为真实分配)
|
||||
- 汇编打印:支持基础指令输出
|
||||
|
||||
> **注意**:循环优化、函数内联、高级寄存器分配等可在基础流程打通后逐步添加。初期可跳过复杂优化。
|
||||
|
||||
### 6. 调试建议
|
||||
- 添加IR打印模块(`SysYPrinter`)验证前端输出
|
||||
- 使用简化测试用例:
|
||||
```c
|
||||
int main() {
|
||||
int a = 1;
|
||||
int b = a + 2;
|
||||
return b;
|
||||
}
|
||||
```
|
||||
- 逐步扩展支持:
|
||||
1. 算术运算 → 2. 条件分支 → 3. 函数调用 → 4. 数组访问
|
||||
|
||||
通过聚焦这些核心模块,你们可以快速打通从SysY到RISC-V的基础编译流程,后续再逐步添加优化传递提升代码质量。
|
||||
@@ -20,7 +20,7 @@ add_executable(sysyc
|
||||
# LLVMIRGenerator.cpp
|
||||
LLVMIRGenerator_1.cpp
|
||||
)
|
||||
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_compile_options(sysyc PRIVATE -frtti)
|
||||
target_link_libraries(sysyc PRIVATE SysYParser)
|
||||
|
||||
|
||||
832
src/IR.cpp
832
src/IR.cpp
@@ -1,586 +1,310 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "range.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
template <typename T>
|
||||
ostream &interleave(ostream &os, const T &container, const string sep = ", ") {
|
||||
auto b = container.begin(), e = container.end();
|
||||
if (b == e)
|
||||
return os;
|
||||
os << *b;
|
||||
for (b = next(b); b != e; b = next(b))
|
||||
os << sep << *b;
|
||||
return os;
|
||||
}
|
||||
static inline ostream &printVarName(ostream &os, const Value *var) {
|
||||
return os << (dyncast<GlobalValue>(var) ? '@' : '%')
|
||||
<< var->getName();
|
||||
}
|
||||
static inline ostream &printBlockName(ostream &os, const BasicBlock *block) {
|
||||
return os << '^' << block->getName();
|
||||
}
|
||||
static inline ostream &printFunctionName(ostream &os, const Function *fn) {
|
||||
return os << '@' << fn->getName();
|
||||
}
|
||||
static inline ostream &printOperand(ostream &os, const Value *value) {
|
||||
auto constant = dyncast<ConstantValue>(value);
|
||||
if (constant) {
|
||||
constant->print(os);
|
||||
return os;
|
||||
}
|
||||
return printVarName(os, value);
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Types
|
||||
//===----------------------------------------------------------------------===//
|
||||
class IRBuilder {
|
||||
private:
|
||||
unsigned labelIndex; ///< 基本块标签编号
|
||||
unsigned tmpIndex; ///< 临时变量编号
|
||||
|
||||
Type *Type::getIntType() {
|
||||
static Type intType(kInt);
|
||||
return &intType;
|
||||
}
|
||||
BasicBlock *block; ///< 当前基本块
|
||||
BasicBlock::iterator position; ///< 当前基本块指令列表位置的迭代器
|
||||
|
||||
Type *Type::getFloatType() {
|
||||
static Type floatType(kFloat);
|
||||
return &floatType;
|
||||
}
|
||||
std::vector<BasicBlock *> trueBlocks; ///< true分支基本块列表
|
||||
std::vector<BasicBlock *> falseBlocks; ///< false分支基本块列表
|
||||
|
||||
Type *Type::getVoidType() {
|
||||
static Type voidType(kVoid);
|
||||
return &voidType;
|
||||
}
|
||||
std::vector<BasicBlock *> breakBlocks; ///< break目标块列表
|
||||
std::vector<BasicBlock *> continueBlocks; ///< continue目标块列表
|
||||
|
||||
Type *Type::getLabelType() {
|
||||
static Type labelType(kLabel);
|
||||
return &labelType;
|
||||
}
|
||||
public:
|
||||
IRBuilder() : labelIndex(0), tmpIndex(0), block(nullptr) {}
|
||||
explicit IRBuilder(BasicBlock *block) : labelIndex(0), tmpIndex(0), block(block), position(block->end()) {}
|
||||
IRBuilder(BasicBlock *block, BasicBlock::iterator position)
|
||||
: labelIndex(0), tmpIndex(0), block(block), position(position) {}
|
||||
|
||||
Type *Type::getPointerType(Type *baseType) {
|
||||
// forward to PointerType
|
||||
return PointerType::get(baseType);
|
||||
}
|
||||
|
||||
Type *Type::getFunctionType(Type *returnType,
|
||||
const vector<Type *> ¶mTypes) {
|
||||
// forward to FunctionType
|
||||
return FunctionType::get(returnType, paramTypes);
|
||||
}
|
||||
|
||||
Type *Type::getArrayType(Type *elementType, const vector<int> &dims) {
|
||||
// forward to ArrayType
|
||||
return ArrayType::get(elementType, dims);
|
||||
}
|
||||
|
||||
ArrayType* Type::asArrayType() const {
|
||||
return isArray() ? dynamic_cast<ArrayType*>(const_cast<Type*>(this)) : nullptr;
|
||||
}
|
||||
|
||||
int Type::getSize() const {
|
||||
switch (kind) {
|
||||
case kInt:
|
||||
case kFloat:
|
||||
return 4;
|
||||
case kLabel:
|
||||
case kPointer:
|
||||
case kFunction:
|
||||
return 8;
|
||||
case kVoid:
|
||||
return 0;
|
||||
case kArray:
|
||||
return asArrayType()->getArraySize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Type::print(ostream &os) const {
|
||||
auto kind = getKind();
|
||||
switch (kind) {
|
||||
case kInt:
|
||||
os << "int";
|
||||
break;
|
||||
case kFloat:
|
||||
os << "float";
|
||||
break;
|
||||
case kVoid:
|
||||
os << "void";
|
||||
break;
|
||||
case kPointer:
|
||||
static_cast<const PointerType *>(this)->getBaseType()->print(os);
|
||||
os << "*";
|
||||
break;
|
||||
case kFunction:
|
||||
static_cast<const FunctionType *>(this)->getReturnType()->print(os);
|
||||
os << "(";
|
||||
interleave(os, static_cast<const FunctionType *>(this)->getParamTypes());
|
||||
os << ")";
|
||||
break;
|
||||
case kLabel:
|
||||
default:
|
||||
cerr << "Unexpected type!\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PointerType *PointerType::get(Type *baseType) {
|
||||
static std::map<Type *, std::unique_ptr<PointerType>> pointerTypes;
|
||||
auto iter = pointerTypes.find(baseType);
|
||||
if (iter != pointerTypes.end())
|
||||
return iter->second.get();
|
||||
auto type = new PointerType(baseType);
|
||||
assert(type);
|
||||
auto result = pointerTypes.emplace(baseType, type);
|
||||
return result.first->second.get();
|
||||
}
|
||||
|
||||
FunctionType *FunctionType::get(Type *returnType,
|
||||
const std::vector<Type *> ¶mTypes) {
|
||||
static std::set<std::unique_ptr<FunctionType>> functionTypes;
|
||||
auto iter =
|
||||
std::find_if(functionTypes.begin(), functionTypes.end(),
|
||||
[&](const std::unique_ptr<FunctionType> &type) -> bool {
|
||||
if (returnType != type->getReturnType() or
|
||||
paramTypes.size() != type->getParamTypes().size())
|
||||
return false;
|
||||
return std::equal(paramTypes.begin(), paramTypes.end(),
|
||||
type->getParamTypes().begin());
|
||||
});
|
||||
if (iter != functionTypes.end())
|
||||
return iter->get();
|
||||
auto type = new FunctionType(returnType, paramTypes);
|
||||
assert(type);
|
||||
auto result = functionTypes.emplace(type);
|
||||
return result.first->get();
|
||||
}
|
||||
|
||||
void Value::replaceAllUsesWith(Value *value) {
|
||||
for (auto &use : uses)
|
||||
use->getUser()->setOperand(use->getIndex(), value);
|
||||
uses.clear();
|
||||
}
|
||||
|
||||
bool Value::isConstant() const {
|
||||
if (dyncast<ConstantValue>(this))
|
||||
return true;
|
||||
if (dyncast<GlobalValue>(this) or
|
||||
dyncast<Function>(this))
|
||||
return true;
|
||||
// if (auto array = dyncast<const ArrayValue *>(this)) {
|
||||
// auto elements = array->getValues();
|
||||
// return all_of(elements.begin(), elements.end(),
|
||||
// [](Value *v) -> bool { return v->isConstant(); });
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 定义静态常量池
|
||||
std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValue::ConstantValueHash> ConstantValue::constantPool;
|
||||
|
||||
// 常量池实现
|
||||
ConstantValue* ConstantValue::get(Type* type, int32_t value) {
|
||||
ConstantValueKey key = {type, ConstantValVariant(value)};
|
||||
public:
|
||||
unsigned getLabelIndex() { return labelIndex++; }
|
||||
unsigned getTmpIndex() { return tmpIndex++; }
|
||||
|
||||
if (auto it = constantPool.find(key); it != constantPool.end()) {
|
||||
return it->second;
|
||||
}
|
||||
BasicBlock *getBasicBlock() const { return block; }
|
||||
BasicBlock::iterator getPosition() const { return position; }
|
||||
|
||||
ConstantValue* constant = new ConstantInt(type, value);
|
||||
constantPool[key] = constant;
|
||||
return constant;
|
||||
}
|
||||
|
||||
ConstantValue* ConstantValue::get(Type* type, float value) {
|
||||
ConstantValueKey key = {type, ConstantValVariant(value)};
|
||||
|
||||
if (auto it = constantPool.find(key); it != constantPool.end()) {
|
||||
return it->second;
|
||||
void setPosition(BasicBlock *block, BasicBlock::iterator position) {
|
||||
this->block = block;
|
||||
this->position = position;
|
||||
}
|
||||
|
||||
ConstantValue* constant = new ConstantFloat(type, value);
|
||||
constantPool[key] = constant;
|
||||
return constant;
|
||||
}
|
||||
void setPosition(BasicBlock::iterator position) { this->position = position; }
|
||||
|
||||
ConstantValue* ConstantValue::getInt32(int32_t value) {
|
||||
return get(Type::getIntType(), value);
|
||||
}
|
||||
|
||||
ConstantValue* ConstantValue::getFloat32(float value) {
|
||||
return get(Type::getFloatType(), value);
|
||||
}
|
||||
|
||||
ConstantValue* ConstantValue::getTrue() {
|
||||
return get(Type::getIntType(), 1);
|
||||
}
|
||||
|
||||
ConstantValue* ConstantValue::getFalse() {
|
||||
return get(Type::getIntType(), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConstantValue::print(std::ostream &os) const {
|
||||
// 根据类型调用相应的打印实现
|
||||
if (auto intConst = dynamic_cast<const ConstantInt*>(this)) {
|
||||
intConst->print(os);
|
||||
}
|
||||
else if (auto floatConst = dynamic_cast<const ConstantFloat*>(this)) {
|
||||
floatConst->print(os);
|
||||
// 控制流管理函数
|
||||
BasicBlock *getBreakBlock() const { return breakBlocks.back(); }
|
||||
BasicBlock *popBreakBlock() {
|
||||
auto result = breakBlocks.back();
|
||||
breakBlocks.pop_back();
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
os << "???"; // 未知常量类型
|
||||
BasicBlock *getContinueBlock() const { return continueBlocks.back(); }
|
||||
BasicBlock *popContinueBlock() {
|
||||
auto result = continueBlocks.back();
|
||||
continueBlocks.pop_back();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void ConstantInt::print(std::ostream &os) const {
|
||||
os << value;
|
||||
}
|
||||
void ConstantFloat::print(std::ostream &os) const {
|
||||
if (value == static_cast<int>(value)) {
|
||||
os << value << ".0"; // 确保输出带小数点
|
||||
} else {
|
||||
os << std::fixed << std::setprecision(6) << value;
|
||||
BasicBlock *getTrueBlock() const { return trueBlocks.back(); }
|
||||
BasicBlock *getFalseBlock() const { return falseBlocks.back(); }
|
||||
BasicBlock *popTrueBlock() {
|
||||
auto result = trueBlocks.back();
|
||||
trueBlocks.pop_back();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
BasicBlock *popFalseBlock() {
|
||||
auto result = falseBlocks.back();
|
||||
falseBlocks.pop_back();
|
||||
return result;
|
||||
}
|
||||
void pushBreakBlock(BasicBlock *block) { breakBlocks.push_back(block); }
|
||||
void pushContinueBlock(BasicBlock *block) { continueBlocks.push_back(block); }
|
||||
void pushTrueBlock(BasicBlock *block) { trueBlocks.push_back(block); }
|
||||
void pushFalseBlock(BasicBlock *block) { falseBlocks.push_back(block); }
|
||||
|
||||
Argument::Argument(Type *type, BasicBlock *block, int index,
|
||||
const std::string &name)
|
||||
: Value(kArgument, type, name), block(block), index(index) {
|
||||
if (not hasName())
|
||||
setName(to_string(block->getParent()->allocateVariableID()));
|
||||
}
|
||||
public:
|
||||
// 指令创建函数
|
||||
Instruction *insertInst(Instruction *inst) {
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
void Argument::print(std::ostream &os) const {
|
||||
assert(hasName());
|
||||
printVarName(os, this) << ": " << *getType();
|
||||
}
|
||||
UnaryInst *createUnaryInst(Instruction::Kind kind, Type *type, Value *operand,
|
||||
const std::string &name = "") {
|
||||
auto inst = new UnaryInst(kind, type, operand, block, name);
|
||||
return static_cast<UnaryInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
BasicBlock::BasicBlock(Function *parent, const std::string &name)
|
||||
: Value(kBasicBlock, Type::getLabelType(), name), parent(parent),
|
||||
instructions(), arguments(), successors(), predecessors() {
|
||||
if (not hasName())
|
||||
setName("bb" + to_string(getParent()->allocateblockID()));
|
||||
}
|
||||
UnaryInst *createNegInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kNeg, Type::getIntType(), operand, name);
|
||||
}
|
||||
|
||||
void BasicBlock::print(std::ostream &os) const {
|
||||
assert(hasName());
|
||||
os << " ";
|
||||
printBlockName(os, this);
|
||||
auto args = getArguments();
|
||||
auto b = args.begin(), e = args.end();
|
||||
if (b != e) {
|
||||
os << '(';
|
||||
printVarName(os, b->get()) << ": " << *b->get()->getType();
|
||||
for (auto &arg : make_range(std::next(b), e)) {
|
||||
os << ", ";
|
||||
printVarName(os, arg.get()) << ": " << *arg->getType();
|
||||
UnaryInst *createNotInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kNot, Type::getIntType(), operand, name);
|
||||
}
|
||||
|
||||
UnaryInst *createFtoIInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFtoI, Type::getIntType(), operand, name);
|
||||
}
|
||||
|
||||
UnaryInst *createBitFtoIInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kBitFtoI, Type::getIntType(), operand, name);
|
||||
}
|
||||
|
||||
UnaryInst *createFNegInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFNeg, Type::getFloatType(), operand, name);
|
||||
}
|
||||
|
||||
UnaryInst *createFNotInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFNot, Type::getIntType(), operand, name);
|
||||
}
|
||||
|
||||
UnaryInst *createIToFInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kItoF, Type::getFloatType(), operand, name);
|
||||
}
|
||||
|
||||
UnaryInst *createBitItoFInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kBitItoF, Type::getFloatType(), operand, name);
|
||||
}
|
||||
|
||||
BinaryInst *createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs,
|
||||
Value *rhs, const std::string &name = "") {
|
||||
auto inst = new BinaryInst(kind, type, lhs, rhs, block, name);
|
||||
return static_cast<BinaryInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
BinaryInst *createAddInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kAdd, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createSubInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSub, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createMulInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kMul, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createDivInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kDiv, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createRemInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kRem, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createICmpEQInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpEQ, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createICmpNEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpNE, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createICmpLTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpLT, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createICmpLEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpLE, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createICmpGTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpGT, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createICmpGEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpGE, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFAddInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFAdd, Type::getFloatType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFSubInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFSub, Type::getFloatType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFMulInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFMul, Type::getFloatType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFDivInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFDiv, Type::getFloatType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFCmpEQInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpEQ, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFCmpNEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpNE, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFCmpLTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpLT, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFCmpLEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpLE, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFCmpGTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpGT, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createFCmpGEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpGE, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createAndInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kAnd, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
BinaryInst *createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
||||
}
|
||||
|
||||
CallInst *createCallInst(Function *callee, const std::vector<Value *> &args,
|
||||
const std::string &name = "") {
|
||||
auto inst = new CallInst(callee, args, block, name);
|
||||
return static_cast<CallInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
ReturnInst *createReturnInst(Value *value = nullptr) {
|
||||
auto inst = new ReturnInst(value, block);
|
||||
return static_cast<ReturnInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
UncondBrInst *createUncondBrInst(BasicBlock *thenBlock,
|
||||
const std::vector<Value *> &args) {
|
||||
auto inst = new UncondBrInst(thenBlock, args, block);
|
||||
return static_cast<UncondBrInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
CondBrInst *createCondBrInst(Value *condition, BasicBlock *thenBlock,
|
||||
BasicBlock *elseBlock,
|
||||
const std::vector<Value *> &thenArgs,
|
||||
const std::vector<Value *> &elseArgs) {
|
||||
auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, elseArgs, block);
|
||||
return static_cast<CondBrInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
AllocaInst *createAllocaInst(Type *type, const std::vector<Value *> &dims = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new AllocaInst(type, dims, block, name);
|
||||
return static_cast<AllocaInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
AllocaInst *createAllocaInstWithoutInsert(Type *type,
|
||||
const std::vector<Value *> &dims = {},
|
||||
BasicBlock *parent = nullptr,
|
||||
const std::string &name = "") {
|
||||
return new AllocaInst(type, dims, parent, name);
|
||||
}
|
||||
|
||||
LoadInst *createLoadInst(Value *pointer, const std::vector<Value *> &indices = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new LoadInst(pointer, indices, block, name);
|
||||
return static_cast<LoadInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
LaInst *createLaInst(Value *pointer, const std::vector<Value *> &indices = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new LaInst(pointer, indices, block, name);
|
||||
return static_cast<LaInst*>(insertInst(inst));
|
||||
}
|
||||
|
||||
GetSubArrayInst *createGetSubArray(LVal *fatherArray,
|
||||
const std::vector<Value *> &indices,
|
||||
const std::string &name = "") {
|
||||
assert(fatherArray->getLValNumDims() > indices.size());
|
||||
std::vector<Value *> subDims;
|
||||
auto dims = fatherArray->getLValDims();
|
||||
auto iter = std::next(dims.begin(), indices.size());
|
||||
while (iter != dims.end()) {
|
||||
subDims.emplace_back(*iter);
|
||||
iter++;
|
||||
}
|
||||
os << ')';
|
||||
|
||||
auto fatherArrayValue = dynamic_cast<Value *>(fatherArray);
|
||||
AllocaInst * childArray = new AllocaInst(fatherArrayValue->getType(), subDims, block);
|
||||
auto inst = new GetSubArrayInst(fatherArray, childArray, indices, block ,name);
|
||||
return static_cast<GetSubArrayInst*>(insertInst(inst));
|
||||
}
|
||||
os << ":\n";
|
||||
for (auto &inst : instructions) {
|
||||
os << " " << *inst << '\n';
|
||||
|
||||
MemsetInst *createMemsetInst(Value *pointer, Value *begin, Value *size,
|
||||
Value *value, const std::string &name = "") {
|
||||
auto inst = new MemsetInst(pointer, begin, size, value, block, name);
|
||||
return static_cast<MemsetInst*>(insertInst(inst));
|
||||
}
|
||||
}
|
||||
|
||||
Instruction::Instruction(Kind kind, Type *type, BasicBlock *parent,
|
||||
const std::string &name)
|
||||
: User(kind, type, name), kind(kind), parent(parent) {
|
||||
if (not type->isVoid() and not hasName())
|
||||
setName(to_string(getFunction()->allocateVariableID()));
|
||||
}
|
||||
|
||||
void CallInst::print(std::ostream &os) const {
|
||||
if (not getType()->isVoid())
|
||||
printVarName(os, this) << " = call ";
|
||||
printFunctionName(os, getCallee()) << '(';
|
||||
auto args = getArguments();
|
||||
auto b = args.begin(), e = args.end();
|
||||
if (b != e) {
|
||||
printOperand(os, *b);
|
||||
for (auto arg : make_range(std::next(b), e)) {
|
||||
os << ", ";
|
||||
printOperand(os, arg);
|
||||
}
|
||||
StoreInst *createStoreInst(Value *value, Value *pointer,
|
||||
const std::vector<Value *> &indices = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new StoreInst(value, pointer, indices, block, name);
|
||||
return static_cast<StoreInst*>(insertInst(inst));
|
||||
}
|
||||
os << ") : " << *getType();
|
||||
}
|
||||
|
||||
void UnaryInst::print(std::ostream &os) const {
|
||||
printVarName(os, this) << " = ";
|
||||
switch (getKind()) {
|
||||
case kNeg:
|
||||
os << "neg";
|
||||
break;
|
||||
case kNot:
|
||||
os << "not";
|
||||
break;
|
||||
case kFNeg:
|
||||
os << "fneg";
|
||||
break;
|
||||
case kFtoI:
|
||||
os << "ftoi";
|
||||
break;
|
||||
case kIToF:
|
||||
os << "itof";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
PhiInst *createPhiInst(Type *type, Value *lhs, BasicBlock *parent,
|
||||
const std::string &name = "") {
|
||||
auto predNum = parent->getNumPredecessors();
|
||||
std::vector<Value *> rhs(predNum, lhs);
|
||||
auto inst = new PhiInst(type, lhs, rhs, lhs, parent, name);
|
||||
parent->getInstructions().emplace(parent->begin(), inst);
|
||||
return inst;
|
||||
}
|
||||
printOperand(os, getOperand()) << " : " << *getType();
|
||||
}
|
||||
};
|
||||
|
||||
void BinaryInst::print(std::ostream &os) const {
|
||||
printVarName(os, this) << " = ";
|
||||
switch (getKind()) {
|
||||
case kAdd:
|
||||
os << "add";
|
||||
break;
|
||||
case kSub:
|
||||
os << "sub";
|
||||
break;
|
||||
case kMul:
|
||||
os << "mul";
|
||||
break;
|
||||
case kDiv:
|
||||
os << "div";
|
||||
break;
|
||||
case kRem:
|
||||
os << "rem";
|
||||
break;
|
||||
case kICmpEQ:
|
||||
os << "icmpeq";
|
||||
break;
|
||||
case kICmpNE:
|
||||
os << "icmpne";
|
||||
break;
|
||||
case kICmpLT:
|
||||
os << "icmplt";
|
||||
break;
|
||||
case kICmpGT:
|
||||
os << "icmpgt";
|
||||
break;
|
||||
case kICmpLE:
|
||||
os << "icmple";
|
||||
break;
|
||||
case kICmpGE:
|
||||
os << "icmpge";
|
||||
break;
|
||||
case kFAdd:
|
||||
os << "fadd";
|
||||
break;
|
||||
case kFSub:
|
||||
os << "fsub";
|
||||
break;
|
||||
case kFMul:
|
||||
os << "fmul";
|
||||
break;
|
||||
case kFDiv:
|
||||
os << "fdiv";
|
||||
break;
|
||||
case kFRem:
|
||||
os << "frem";
|
||||
break;
|
||||
case kFCmpEQ:
|
||||
os << "fcmpeq";
|
||||
break;
|
||||
case kFCmpNE:
|
||||
os << "fcmpne";
|
||||
break;
|
||||
case kFCmpLT:
|
||||
os << "fcmplt";
|
||||
break;
|
||||
case kFCmpGT:
|
||||
os << "fcmpgt";
|
||||
break;
|
||||
case kFCmpLE:
|
||||
os << "fcmple";
|
||||
break;
|
||||
case kFCmpGE:
|
||||
os << "fcmpge";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
os << ' ';
|
||||
printOperand(os, getLhs()) << ", ";
|
||||
printOperand(os, getRhs()) << " : " << *getType();
|
||||
}
|
||||
|
||||
void ReturnInst::print(std::ostream &os) const {
|
||||
os << "return";
|
||||
if (auto value = getReturnValue()) {
|
||||
os << ' ';
|
||||
printOperand(os, value) << " : " << *value->getType();
|
||||
}
|
||||
}
|
||||
|
||||
void UncondBrInst::print(std::ostream &os) const {
|
||||
os << "br ";
|
||||
printBlockName(os, getBlock());
|
||||
auto args = getArguments();
|
||||
auto b = args.begin(), e = args.end();
|
||||
if (b != e) {
|
||||
os << '(';
|
||||
printOperand(os, *b);
|
||||
for (auto arg : make_range(std::next(b), e)) {
|
||||
os << ", ";
|
||||
printOperand(os, arg);
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
}
|
||||
|
||||
void CondBrInst::print(std::ostream &os) const {
|
||||
os << "condbr ";
|
||||
printOperand(os, getCondition()) << ", ";
|
||||
printBlockName(os, getThenBlock());
|
||||
{
|
||||
auto args = getThenArguments();
|
||||
auto b = args.begin(), e = args.end();
|
||||
if (b != e) {
|
||||
os << '(';
|
||||
printOperand(os, *b);
|
||||
for (auto arg : make_range(std::next(b), e)) {
|
||||
os << ", ";
|
||||
printOperand(os, arg);
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
}
|
||||
os << ", ";
|
||||
printBlockName(os, getElseBlock());
|
||||
{
|
||||
auto args = getElseArguments();
|
||||
auto b = args.begin(), e = args.end();
|
||||
if (b != e) {
|
||||
os << '(';
|
||||
printOperand(os, *b);
|
||||
for (auto arg : make_range(std::next(b), e)) {
|
||||
os << ", ";
|
||||
printOperand(os, arg);
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AllocaInst::print(std::ostream &os) const {
|
||||
if (getNumDims())
|
||||
cerr << "not implemented yet\n";
|
||||
printVarName(os, this) << " = ";
|
||||
os << "alloca "
|
||||
<< *static_cast<const PointerType *>(getType())->getBaseType();
|
||||
os << " : " << *getType();
|
||||
}
|
||||
|
||||
void LoadInst::print(std::ostream &os) const {
|
||||
if (getNumIndices())
|
||||
cerr << "not implemented yet\n";
|
||||
printVarName(os, this) << " = ";
|
||||
os << "load ";
|
||||
printOperand(os, getPointer()) << " : " << *getType();
|
||||
}
|
||||
|
||||
void StoreInst::print(std::ostream &os) const {
|
||||
if (getNumIndices())
|
||||
cerr << "not implemented yet\n";
|
||||
os << "store ";
|
||||
printOperand(os, getValue()) << ", ";
|
||||
printOperand(os, getPointer()) << " : " << *getValue()->getType();
|
||||
}
|
||||
|
||||
void Function::print(std::ostream &os) const {
|
||||
auto returnType = getReturnType();
|
||||
auto paramTypes = getParamTypes();
|
||||
os << *returnType << ' ';
|
||||
printFunctionName(os, this) << '(';
|
||||
auto b = paramTypes.begin(), e = paramTypes.end();
|
||||
if (b != e) {
|
||||
os << *(*b);
|
||||
for (auto type : make_range(std::next(b), e))
|
||||
os << ", " << *type;
|
||||
}
|
||||
os << ") {\n";
|
||||
for (auto &bb : getBasicBlocks()) {
|
||||
os << *bb << '\n';
|
||||
}
|
||||
os << "}";
|
||||
}
|
||||
|
||||
void Module::print(std::ostream &os) const {
|
||||
for (auto &value : children)
|
||||
os << *value << '\n';
|
||||
}
|
||||
|
||||
// ArrayValue *ArrayValue::get(Type *type, const vector<Value *> &values) {
|
||||
// static map<pair<Type *, size_t>, unique_ptr<ArrayValue>> arrayConstants;
|
||||
// hash<string> hasher;
|
||||
// auto key = make_pair(
|
||||
// type, hasher(string(reinterpret_cast<const char *>(values.data()),
|
||||
// values.size() * sizeof(Value *))));
|
||||
|
||||
// auto iter = arrayConstants.find(key);
|
||||
// if (iter != arrayConstants.end())
|
||||
// return iter->second.get();
|
||||
// auto constant = new ArrayValue(type, values);
|
||||
// assert(constant);
|
||||
// auto result = arrayConstants.emplace(key, constant);
|
||||
// return result.first->second.get();
|
||||
// }
|
||||
|
||||
// ArrayValue *ArrayValue::get(const std::vector<int> &values) {
|
||||
// vector<Value *> vals(values.size(), nullptr);
|
||||
// std::transform(values.begin(), values.end(), vals.begin(),
|
||||
// [](int v) { return ConstantValue::get(v); });
|
||||
// return get(Type::getIntType(), vals);
|
||||
// }
|
||||
|
||||
// ArrayValue *ArrayValue::get(const std::vector<float> &values) {
|
||||
// vector<Value *> vals(values.size(), nullptr);
|
||||
// std::transform(values.begin(), values.end(), vals.begin(),
|
||||
// [](float v) { return ConstantValue::get(v); });
|
||||
// return get(Type::getFloatType(), vals);
|
||||
// }
|
||||
|
||||
void User::setOperand(int index, Value *value) {
|
||||
assert(index < getNumOperands());
|
||||
operands[index].setValue(value);
|
||||
}
|
||||
|
||||
void User::replaceOperand(int index, Value *value) {
|
||||
assert(index < getNumOperands());
|
||||
auto &use = operands[index];
|
||||
use.getValue()->removeUse(&use);
|
||||
use.setValue(value);
|
||||
}
|
||||
|
||||
CallInst::CallInst(Function *callee, const std::vector<Value *> &args,
|
||||
BasicBlock *parent, const std::string &name)
|
||||
: Instruction(kCall, callee->getReturnType(), parent, name) {
|
||||
addOperand(callee);
|
||||
for (auto arg : args)
|
||||
addOperand(arg);
|
||||
}
|
||||
|
||||
Function *CallInst::getCallee() const {
|
||||
return dyncast<Function>(getOperand(0));
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
} // namespace sysy
|
||||
|
||||
0
src/SysYIRAnalyser.cpp
Normal file
0
src/SysYIRAnalyser.cpp
Normal file
@@ -834,204 +834,4 @@ std::any SysYIRGenerator::visitConstExp(SysYParser::ConstExpContext* ctx) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* begin
|
||||
std::any SysYIRGenerator::visitConstGlobalDecl(SysYParser::ConstDeclContext *ctx, Type* type) {
|
||||
std::vector<Value *> values;
|
||||
for (auto constDef : ctx->constDef()) {
|
||||
|
||||
auto name = constDef->Ident()->getText();
|
||||
// get its dimensions
|
||||
vector<Value *> dims;
|
||||
for (auto dim : constDef->constExp())
|
||||
dims.push_back(any_cast<Value *>(dim->accept(this)));
|
||||
|
||||
if (dims.size() == 0) {
|
||||
auto init = constDef->ASSIGN() ? any_cast<Value *>((constDef->constInitVal()->constExp()->accept(this)))
|
||||
: nullptr;
|
||||
if (init && isa<ConstantValue>(init)){
|
||||
Type *btype = type->as<PointerType>()->getBaseType();
|
||||
if (btype->isInt() && init->getType()->isFloat())
|
||||
init = ConstantValue::get((int)dynamic_cast<ConstantValue *>(init)->getFloat());
|
||||
else if (btype->isFloat() && init->getType()->isInt())
|
||||
init = ConstantValue::get((float)dynamic_cast<ConstantValue *>(init)->getInt());
|
||||
}
|
||||
|
||||
auto global_value = module->createGlobalValue(name, type, dims, init);
|
||||
|
||||
symbols_table.insert(name, global_value);
|
||||
values.push_back(global_value);
|
||||
}
|
||||
else{
|
||||
auto init = constDef->ASSIGN() ? any_cast<Value *>(dims[0])
|
||||
: nullptr;
|
||||
auto global_value = module->createGlobalValue(name, type, dims, init);
|
||||
if (constDef->ASSIGN()) {
|
||||
d = 0;
|
||||
n = 0;
|
||||
path.clear();
|
||||
path = vector<int>(dims.size(), 0);
|
||||
isalloca = false;
|
||||
current_type = global_value->getType()->as<PointerType>()->getBaseType();
|
||||
current_global = global_value;
|
||||
numdims = global_value->getNumDims();
|
||||
for (auto init : constDef->constInitVal()->constInitVal())
|
||||
init->accept(this);
|
||||
// visitConstInitValue(init);
|
||||
}
|
||||
symbols_table.insert(name, global_value);
|
||||
values.push_back(global_value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
std::any SysYIRGenerator::visitVarGlobalDecl(SysYParser::VarDeclContext *ctx, Type* type){
|
||||
std::vector<Value *> values;
|
||||
for (auto varDef : ctx->varDef()) {
|
||||
|
||||
auto name = varDef->Ident()->getText();
|
||||
// get its dimensions
|
||||
vector<Value *> dims;
|
||||
for (auto dim : varDef->constExp())
|
||||
dims.push_back(any_cast<Value *>(dim->accept(this)));
|
||||
|
||||
if (dims.size() == 0) {
|
||||
auto init = varDef->ASSIGN() ? any_cast<Value *>((varDef->initVal()->exp()->accept(this)))
|
||||
: nullptr;
|
||||
if (init && isa<ConstantValue>(init)){
|
||||
Type *btype = type->as<PointerType>()->getBaseType();
|
||||
if (btype->isInt() && init->getType()->isFloat())
|
||||
init = ConstantValue::get((int)dynamic_cast<ConstantValue *>(init)->getFloat());
|
||||
else if (btype->isFloat() && init->getType()->isInt())
|
||||
init = ConstantValue::get((float)dynamic_cast<ConstantValue *>(init)->getInt());
|
||||
}
|
||||
|
||||
auto global_value = module->createGlobalValue(name, type, dims, init);
|
||||
|
||||
symbols_table.insert(name, global_value);
|
||||
values.push_back(global_value);
|
||||
}
|
||||
else{
|
||||
auto init = varDef->ASSIGN() ? any_cast<Value *>(dims[0])
|
||||
: nullptr;
|
||||
auto global_value = module->createGlobalValue(name, type, dims, init);
|
||||
if (varDef->ASSIGN()) {
|
||||
d = 0;
|
||||
n = 0;
|
||||
path.clear();
|
||||
path = vector<int>(dims.size(), 0);
|
||||
isalloca = false;
|
||||
current_type = global_value->getType()->as<PointerType>()->getBaseType();
|
||||
current_global = global_value;
|
||||
numdims = global_value->getNumDims();
|
||||
for (auto init : varDef->initVal()->initVal())
|
||||
init->accept(this);
|
||||
// visitInitValue(init);
|
||||
}
|
||||
symbols_table.insert(name, global_value);
|
||||
values.push_back(global_value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
std::any SysYIRGenerator::visitConstLocalDecl(SysYParser::ConstDeclContext *ctx, Type* type){
|
||||
std::vector<Value *> values;
|
||||
// handle variables
|
||||
for (auto constDef : ctx->constDef()) {
|
||||
|
||||
auto name = constDef->Ident()->getText();
|
||||
vector<Value *> dims;
|
||||
for (auto dim : constDef->constExp())
|
||||
dims.push_back(any_cast<Value *>(dim->accept(this)));
|
||||
auto alloca = builder.createAllocaInst(type, dims, name);
|
||||
symbols_table.insert(name, alloca);
|
||||
|
||||
if (constDef->ASSIGN()) {
|
||||
if (alloca->getNumDims() == 0) {
|
||||
|
||||
auto value = any_cast<Value *>(constDef->constInitVal()->constExp()->accept(this));
|
||||
|
||||
if (isa<ConstantValue>(value)) {
|
||||
if (ctx->bType()->INT() && dynamic_cast<ConstantValue *>(value)->isFloat())
|
||||
value = ConstantValue::get((int)dynamic_cast<ConstantValue *>(value)->getFloat());
|
||||
else if (ctx->bType()->FLOAT() && dynamic_cast<ConstantValue *>(value)->isInt())
|
||||
value = ConstantValue::get((float)dynamic_cast<ConstantValue *>(value)->getInt());
|
||||
}
|
||||
else if (alloca->getType()->as<PointerType>()->getBaseType()->isInt() && value->getType()->isFloat())
|
||||
value = builder.createFtoIInst(value);
|
||||
else if (alloca->getType()->as<PointerType>()->getBaseType()->isFloat() && value->getType()->isInt())
|
||||
value = builder.createIToFInst(value);
|
||||
|
||||
auto store = builder.createStoreInst(value, alloca);
|
||||
}
|
||||
else{
|
||||
d = 0;
|
||||
n = 0;
|
||||
path.clear();
|
||||
path = vector<int>(alloca->getNumDims(), 0);
|
||||
isalloca = true;
|
||||
current_alloca = alloca;
|
||||
current_type = alloca->getType()->as<PointerType>()->getBaseType();
|
||||
numdims = alloca->getNumDims();
|
||||
for (auto init : constDef->constInitVal()->constInitVal())
|
||||
init->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
values.push_back(alloca);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
std::any SysYIRGenerator::visitVarLocalDecl(SysYParser::VarDeclContext *ctx, Type* type){
|
||||
std::vector<Value *> values;
|
||||
for (auto varDef : ctx->varDef()) {
|
||||
|
||||
auto name = varDef->Ident()->getText();
|
||||
vector<Value *> dims;
|
||||
for (auto dim : varDef->constExp())
|
||||
dims.push_back(any_cast<Value *>(dim->accept(this)));
|
||||
auto alloca = builder.createAllocaInst(type, dims, name);
|
||||
symbols_table.insert(name, alloca);
|
||||
|
||||
if (varDef->ASSIGN()) {
|
||||
if (alloca->getNumDims() == 0) {
|
||||
|
||||
auto value = any_cast<Value *>(varDef->initVal()->exp()->accept(this));
|
||||
|
||||
if (isa<ConstantValue>(value)) {
|
||||
if (ctx->bType()->INT() && dynamic_cast<ConstantValue *>(value)->isFloat())
|
||||
value = ConstantValue::get((int)dynamic_cast<ConstantValue *>(value)->getFloat());
|
||||
else if (ctx->bType()->FLOAT() && dynamic_cast<ConstantValue *>(value)->isInt())
|
||||
value = ConstantValue::get((float)dynamic_cast<ConstantValue *>(value)->getInt());
|
||||
}
|
||||
else if (alloca->getType()->as<PointerType>()->getBaseType()->isInt() && value->getType()->isFloat())
|
||||
value = builder.createFtoIInst(value);
|
||||
else if (alloca->getType()->as<PointerType>()->getBaseType()->isFloat() && value->getType()->isInt())
|
||||
value = builder.createIToFInst(value);
|
||||
|
||||
auto store = builder.createStoreInst(value, alloca);
|
||||
}
|
||||
else{
|
||||
d = 0;
|
||||
n = 0;
|
||||
path.clear();
|
||||
path = vector<int>(alloca->getNumDims(), 0);
|
||||
isalloca = true;
|
||||
current_alloca = alloca;
|
||||
current_type = alloca->getType()->as<PointerType>()->getBaseType();
|
||||
numdims = alloca->getNumDims();
|
||||
for (auto init : varDef->initVal()->initVal())
|
||||
init->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
values.push_back(alloca);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
end
|
||||
*/
|
||||
|
||||
} // namespace sysy
|
||||
1319
src/include/IR.h
Normal file
1319
src/include/IR.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,14 +8,23 @@ namespace sysy {
|
||||
|
||||
class IRBuilder {
|
||||
private:
|
||||
BasicBlock *block;
|
||||
BasicBlock::iterator position;
|
||||
unsigned labelIndex; ///< 基本块标签编号
|
||||
unsigned tmpIndex; ///< 临时变量编号
|
||||
|
||||
BasicBlock *block; ///< 当前基本块
|
||||
BasicBlock::iterator position; ///< 当前基本块指令列表位置的迭代器
|
||||
|
||||
std::vector<BasicBlock *> trueBlocks; ///< true分支基本块列表
|
||||
std::vector<BasicBlock *> falseBlocks; ///< false分支基本块列表
|
||||
|
||||
std::vector<BasicBlock *> breakBlocks; ///< break目标块列表
|
||||
std::vector<BasicBlock *> continueBlocks; ///< continue目标块列表
|
||||
|
||||
public:
|
||||
IRBuilder() = default;
|
||||
IRBuilder(BasicBlock *block) : block(block), position(block->end()) {}
|
||||
IRBuilder() : labelIndex(0), tmpIndex(0), block(nullptr) {}
|
||||
explicit IRBuilder(BasicBlock *block) : labelIndex(0), tmpIndex(0), block(block), position(block->end()) {}
|
||||
IRBuilder(BasicBlock *block, BasicBlock::iterator position)
|
||||
: block(block), position(position) {}
|
||||
: labelIndex(0), tmpIndex(0), block(block), position(position) {}
|
||||
|
||||
public:
|
||||
BasicBlock *getBasicBlock() const { return block; }
|
||||
@@ -60,7 +69,7 @@ public:
|
||||
name);
|
||||
}
|
||||
UnaryInst *createIToFInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kIToF, Type::getFloatType(), operand,
|
||||
return createUnaryInst(Instruction::kItoF, Type::getFloatType(), operand,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs,
|
||||
0
src/include/SysYIRAnalyser.h
Normal file
0
src/include/SysYIRAnalyser.h
Normal file
@@ -134,15 +134,6 @@ public:
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override;
|
||||
std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
|
||||
|
||||
private:
|
||||
std::any visitConstGlobalDecl(SysYParser::ConstDeclContext *ctx, Type* type);
|
||||
std::any visitVarGlobalDecl(SysYParser::VarDeclContext *ctx, Type* type);
|
||||
std::any visitConstLocalDecl(SysYParser::ConstDeclContext *ctx, Type* type);
|
||||
std::any visitVarLocalDecl(SysYParser::VarDeclContext *ctx, Type* type);
|
||||
Type *getArithmeticResultType(Type *lhs, Type *rhs) {
|
||||
assert(lhs->isIntOrFloat() and rhs->isIntOrFloat());
|
||||
return lhs == rhs ? lhs : Type::getFloatType();
|
||||
}
|
||||
|
||||
}; // class SysYIRGenerator
|
||||
|
||||
Reference in New Issue
Block a user