更新目录结构,修改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.cpp
|
||||||
LLVMIRGenerator_1.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_compile_options(sysyc PRIVATE -frtti)
|
||||||
target_link_libraries(sysyc PRIVATE SysYParser)
|
target_link_libraries(sysyc PRIVATE SysYParser)
|
||||||
|
|
||||||
|
|||||||
832
src/IR.cpp
832
src/IR.cpp
@@ -1,586 +1,310 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include "IR.h"
|
#include "IR.h"
|
||||||
#include "range.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <sstream>
|
||||||
#include <set>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <variant>
|
|
||||||
#include <iomanip>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
template <typename T>
|
class IRBuilder {
|
||||||
ostream &interleave(ostream &os, const T &container, const string sep = ", ") {
|
private:
|
||||||
auto b = container.begin(), e = container.end();
|
unsigned labelIndex; ///< 基本块标签编号
|
||||||
if (b == e)
|
unsigned tmpIndex; ///< 临时变量编号
|
||||||
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
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
Type *Type::getIntType() {
|
BasicBlock *block; ///< 当前基本块
|
||||||
static Type intType(kInt);
|
BasicBlock::iterator position; ///< 当前基本块指令列表位置的迭代器
|
||||||
return &intType;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *Type::getFloatType() {
|
std::vector<BasicBlock *> trueBlocks; ///< true分支基本块列表
|
||||||
static Type floatType(kFloat);
|
std::vector<BasicBlock *> falseBlocks; ///< false分支基本块列表
|
||||||
return &floatType;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *Type::getVoidType() {
|
std::vector<BasicBlock *> breakBlocks; ///< break目标块列表
|
||||||
static Type voidType(kVoid);
|
std::vector<BasicBlock *> continueBlocks; ///< continue目标块列表
|
||||||
return &voidType;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *Type::getLabelType() {
|
public:
|
||||||
static Type labelType(kLabel);
|
IRBuilder() : labelIndex(0), tmpIndex(0), block(nullptr) {}
|
||||||
return &labelType;
|
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) {
|
public:
|
||||||
// forward to PointerType
|
unsigned getLabelIndex() { return labelIndex++; }
|
||||||
return PointerType::get(baseType);
|
unsigned getTmpIndex() { return tmpIndex++; }
|
||||||
}
|
|
||||||
|
|
||||||
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)};
|
|
||||||
|
|
||||||
if (auto it = constantPool.find(key); it != constantPool.end()) {
|
BasicBlock *getBasicBlock() const { return block; }
|
||||||
return it->second;
|
BasicBlock::iterator getPosition() const { return position; }
|
||||||
}
|
|
||||||
|
|
||||||
ConstantValue* constant = new ConstantInt(type, value);
|
void setPosition(BasicBlock *block, BasicBlock::iterator position) {
|
||||||
constantPool[key] = constant;
|
this->block = block;
|
||||||
return constant;
|
this->position = position;
|
||||||
}
|
|
||||||
|
|
||||||
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::iterator position) { this->position = position; }
|
||||||
ConstantValue* constant = new ConstantFloat(type, value);
|
|
||||||
constantPool[key] = constant;
|
|
||||||
return constant;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstantValue* ConstantValue::getInt32(int32_t value) {
|
// 控制流管理函数
|
||||||
return get(Type::getIntType(), value);
|
BasicBlock *getBreakBlock() const { return breakBlocks.back(); }
|
||||||
}
|
BasicBlock *popBreakBlock() {
|
||||||
|
auto result = breakBlocks.back();
|
||||||
ConstantValue* ConstantValue::getFloat32(float value) {
|
breakBlocks.pop_back();
|
||||||
return get(Type::getFloatType(), value);
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else {
|
BasicBlock *getContinueBlock() const { return continueBlocks.back(); }
|
||||||
os << "???"; // 未知常量类型
|
BasicBlock *popContinueBlock() {
|
||||||
|
auto result = continueBlocks.back();
|
||||||
|
continueBlocks.pop_back();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
BasicBlock *getTrueBlock() const { return trueBlocks.back(); }
|
||||||
|
BasicBlock *getFalseBlock() const { return falseBlocks.back(); }
|
||||||
void ConstantInt::print(std::ostream &os) const {
|
BasicBlock *popTrueBlock() {
|
||||||
os << value;
|
auto result = trueBlocks.back();
|
||||||
}
|
trueBlocks.pop_back();
|
||||||
void ConstantFloat::print(std::ostream &os) const {
|
return result;
|
||||||
if (value == static_cast<int>(value)) {
|
|
||||||
os << value << ".0"; // 确保输出带小数点
|
|
||||||
} else {
|
|
||||||
os << std::fixed << std::setprecision(6) << value;
|
|
||||||
}
|
}
|
||||||
}
|
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,
|
public:
|
||||||
const std::string &name)
|
// 指令创建函数
|
||||||
: Value(kArgument, type, name), block(block), index(index) {
|
Instruction *insertInst(Instruction *inst) {
|
||||||
if (not hasName())
|
assert(inst);
|
||||||
setName(to_string(block->getParent()->allocateVariableID()));
|
block->getInstructions().emplace(position, inst);
|
||||||
}
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
void Argument::print(std::ostream &os) const {
|
UnaryInst *createUnaryInst(Instruction::Kind kind, Type *type, Value *operand,
|
||||||
assert(hasName());
|
const std::string &name = "") {
|
||||||
printVarName(os, this) << ": " << *getType();
|
auto inst = new UnaryInst(kind, type, operand, block, name);
|
||||||
}
|
return static_cast<UnaryInst*>(insertInst(inst));
|
||||||
|
}
|
||||||
|
|
||||||
BasicBlock::BasicBlock(Function *parent, const std::string &name)
|
UnaryInst *createNegInst(Value *operand, const std::string &name = "") {
|
||||||
: Value(kBasicBlock, Type::getLabelType(), name), parent(parent),
|
return createUnaryInst(Instruction::kNeg, Type::getIntType(), operand, name);
|
||||||
instructions(), arguments(), successors(), predecessors() {
|
}
|
||||||
if (not hasName())
|
|
||||||
setName("bb" + to_string(getParent()->allocateblockID()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BasicBlock::print(std::ostream &os) const {
|
UnaryInst *createNotInst(Value *operand, const std::string &name = "") {
|
||||||
assert(hasName());
|
return createUnaryInst(Instruction::kNot, Type::getIntType(), operand, name);
|
||||||
os << " ";
|
}
|
||||||
printBlockName(os, this);
|
|
||||||
auto args = getArguments();
|
UnaryInst *createFtoIInst(Value *operand, const std::string &name = "") {
|
||||||
auto b = args.begin(), e = args.end();
|
return createUnaryInst(Instruction::kFtoI, Type::getIntType(), operand, name);
|
||||||
if (b != e) {
|
}
|
||||||
os << '(';
|
|
||||||
printVarName(os, b->get()) << ": " << *b->get()->getType();
|
UnaryInst *createBitFtoIInst(Value *operand, const std::string &name = "") {
|
||||||
for (auto &arg : make_range(std::next(b), e)) {
|
return createUnaryInst(Instruction::kBitFtoI, Type::getIntType(), operand, name);
|
||||||
os << ", ";
|
}
|
||||||
printVarName(os, arg.get()) << ": " << *arg->getType();
|
|
||||||
|
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) {
|
MemsetInst *createMemsetInst(Value *pointer, Value *begin, Value *size,
|
||||||
os << " " << *inst << '\n';
|
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,
|
StoreInst *createStoreInst(Value *value, Value *pointer,
|
||||||
const std::string &name)
|
const std::vector<Value *> &indices = {},
|
||||||
: User(kind, type, name), kind(kind), parent(parent) {
|
const std::string &name = "") {
|
||||||
if (not type->isVoid() and not hasName())
|
auto inst = new StoreInst(value, pointer, indices, block, name);
|
||||||
setName(to_string(getFunction()->allocateVariableID()));
|
return static_cast<StoreInst*>(insertInst(inst));
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
os << ") : " << *getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnaryInst::print(std::ostream &os) const {
|
PhiInst *createPhiInst(Type *type, Value *lhs, BasicBlock *parent,
|
||||||
printVarName(os, this) << " = ";
|
const std::string &name = "") {
|
||||||
switch (getKind()) {
|
auto predNum = parent->getNumPredecessors();
|
||||||
case kNeg:
|
std::vector<Value *> rhs(predNum, lhs);
|
||||||
os << "neg";
|
auto inst = new PhiInst(type, lhs, rhs, lhs, parent, name);
|
||||||
break;
|
parent->getInstructions().emplace(parent->begin(), inst);
|
||||||
case kNot:
|
return inst;
|
||||||
os << "not";
|
|
||||||
break;
|
|
||||||
case kFNeg:
|
|
||||||
os << "fneg";
|
|
||||||
break;
|
|
||||||
case kFtoI:
|
|
||||||
os << "ftoi";
|
|
||||||
break;
|
|
||||||
case kIToF:
|
|
||||||
os << "itof";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
printOperand(os, getOperand()) << " : " << *getType();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
void BinaryInst::print(std::ostream &os) const {
|
} // namespace sysy
|
||||||
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
|
|
||||||
|
|||||||
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;
|
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
|
} // 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 {
|
class IRBuilder {
|
||||||
private:
|
private:
|
||||||
BasicBlock *block;
|
unsigned labelIndex; ///< 基本块标签编号
|
||||||
BasicBlock::iterator position;
|
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:
|
public:
|
||||||
IRBuilder() = default;
|
IRBuilder() : labelIndex(0), tmpIndex(0), block(nullptr) {}
|
||||||
IRBuilder(BasicBlock *block) : block(block), position(block->end()) {}
|
explicit IRBuilder(BasicBlock *block) : labelIndex(0), tmpIndex(0), block(block), position(block->end()) {}
|
||||||
IRBuilder(BasicBlock *block, BasicBlock::iterator position)
|
IRBuilder(BasicBlock *block, BasicBlock::iterator position)
|
||||||
: block(block), position(position) {}
|
: labelIndex(0), tmpIndex(0), block(block), position(position) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BasicBlock *getBasicBlock() const { return block; }
|
BasicBlock *getBasicBlock() const { return block; }
|
||||||
@@ -60,7 +69,7 @@ public:
|
|||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
UnaryInst *createIToFInst(Value *operand, const std::string &name = "") {
|
UnaryInst *createIToFInst(Value *operand, const std::string &name = "") {
|
||||||
return createUnaryInst(Instruction::kIToF, Type::getFloatType(), operand,
|
return createUnaryInst(Instruction::kItoF, Type::getFloatType(), operand,
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
BinaryInst *createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs,
|
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 visitLOrExp(SysYParser::LOrExpContext *ctx) override;
|
||||||
std::any visitConstExp(SysYParser::ConstExpContext *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
|
}; // class SysYIRGenerator
|
||||||
|
|
||||||
Reference in New Issue
Block a user