[IR]重构数组地址相关指令
增加GEP指令以及相关方法 新增数组Array Type 删除无用指令(GetSubArray,LA) 删除冗余类定义(Lval) 修复中间代码生成逻辑 测试通过所以test目录下的文件 TODO:后端展开数组计算地址仅需要针对GEP指令展开
This commit is contained in:
@@ -3,12 +3,11 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "IR.h"
|
||||
#include "IR.h" // 确保IR.h包含了ArrayType、GetElementPtrInst等的定义
|
||||
|
||||
namespace sysy {
|
||||
|
||||
void SysYPrinter::printIR() {
|
||||
|
||||
const auto &functions = pModule->getFunctions();
|
||||
|
||||
//TODO: Print target datalayout and triple (minimal required by LLVM)
|
||||
@@ -36,11 +35,18 @@ std::string SysYPrinter::getTypeString(Type *type) {
|
||||
return "i32";
|
||||
} else if (type->isFloat()) {
|
||||
return "float";
|
||||
|
||||
} else if (auto ptrType = dynamic_cast<PointerType*>(type)) {
|
||||
// 递归打印指针指向的类型,然后加上 '*'
|
||||
return getTypeString(ptrType->getBaseType()) + "*";
|
||||
} else if (auto ptrType = dynamic_cast<FunctionType*>(type)) {
|
||||
return getTypeString(ptrType->getReturnType());
|
||||
} else if (auto funcType = dynamic_cast<FunctionType*>(type)) {
|
||||
// 对于函数类型,打印其返回类型
|
||||
// 注意:这里可能需要更完整的函数签名打印,取决于你的IR表示方式
|
||||
// 比如:`retType (paramType1, paramType2, ...)`
|
||||
// 但为了简化和LLVM IR兼容性,通常在定义时完整打印
|
||||
return getTypeString(funcType->getReturnType());
|
||||
} else if (auto arrayType = dynamic_cast<ArrayType*>(type)) { // 新增:处理数组类型
|
||||
// 打印格式为 [num_elements x element_type]
|
||||
return "[" + std::to_string(arrayType->getNumElements()) + " x " + getTypeString(arrayType->getElementType()) + "]";
|
||||
}
|
||||
assert(false && "Unsupported type");
|
||||
return "";
|
||||
@@ -51,15 +57,23 @@ std::string SysYPrinter::getValueName(Value *value) {
|
||||
return "@" + global->getName();
|
||||
} else if (auto inst = dynamic_cast<Instruction*>(value)) {
|
||||
return "%" + inst->getName();
|
||||
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) {
|
||||
if (constVal->isFloat()) {
|
||||
return std::to_string(constVal->getFloat());
|
||||
} else if (auto constInt = dynamic_cast<ConstantInteger*>(value)) { // 优先匹配具体的常量类型
|
||||
return std::to_string(constInt->getInt());
|
||||
} else if (auto constFloat = dynamic_cast<ConstantFloating*>(value)) { // 优先匹配具体的常量类型
|
||||
return std::to_string(constFloat->getFloat());
|
||||
} else if (auto constUndef = dynamic_cast<UndefinedValue*>(value)) { // 如果有Undef类型
|
||||
return "undef";
|
||||
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) { // fallback for generic ConstantValue
|
||||
// 这里的逻辑可能需要根据你ConstantValue的实际设计调整
|
||||
// 确保它能处理所有可能的ConstantValue
|
||||
if (constVal->getType()->isFloat()) {
|
||||
return std::to_string(constVal->getFloat());
|
||||
}
|
||||
return std::to_string(constVal->getInt());
|
||||
} else if (auto constVar = dynamic_cast<ConstantVariable*>(value)) {
|
||||
return constVar->getName();
|
||||
return constVar->getName(); // 假设ConstantVariable有自己的名字或通过getByIndices获取值
|
||||
}
|
||||
assert(false && "Unknown value type");
|
||||
assert(false && "Unknown value type or unable to get value name");
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -77,44 +91,35 @@ void SysYPrinter::printGlobalVariable() {
|
||||
for (const auto &global : globals) {
|
||||
std::cout << "@" << global->getName() << " = global ";
|
||||
|
||||
auto baseType = dynamic_cast<PointerType *>(global->getType())->getBaseType();
|
||||
printType(baseType);
|
||||
|
||||
if (global->getNumDims() > 0) {
|
||||
// Array type
|
||||
std::cout << " [";
|
||||
for (unsigned i = 0; i < global->getNumDims(); i++) {
|
||||
if (i > 0) std::cout << " x ";
|
||||
std::cout << getValueName(global->getDim(i));
|
||||
}
|
||||
std::cout << "]";
|
||||
}
|
||||
// 全局变量的类型是一个指针,指向其基类型 (可能是 ArrayType 或 Integer/FloatType)
|
||||
auto globalVarBaseType = dynamic_cast<PointerType *>(global->getType())->getBaseType();
|
||||
printType(globalVarBaseType); // 打印全局变量的实际类型 (例如 i32 或 [10 x i32])
|
||||
|
||||
std::cout << " ";
|
||||
|
||||
if (global->getNumDims() > 0) {
|
||||
// Array initializer
|
||||
std::cout << "[";
|
||||
auto values = global->getInitValues();
|
||||
auto counterValues = values.getValues();
|
||||
auto counterNumbers = values.getNumbers();
|
||||
// 检查是否是数组类型 (通过检查 globalVarBaseType 是否是 ArrayType)
|
||||
if (globalVarBaseType->isArray()) {
|
||||
// 数组初始化器
|
||||
std::cout << "["; // LLVM IR 数组初始化器格式: [type value, type value, ...]
|
||||
auto values = global->getInitValues(); // 假设 getInitValues() 返回一个 ValueCounter
|
||||
const std::vector<sysy::Value *> &counterValues = values.getValues(); // 获取所有值
|
||||
|
||||
for (size_t i = 0; i < counterNumbers.size(); i++) {
|
||||
for (size_t i = 0; i < counterValues.size(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
if (baseType->isFloat()) {
|
||||
std::cout << "float " << dynamic_cast<ConstantValue*>(counterValues[i])->getFloat();
|
||||
} else {
|
||||
std::cout << "i32 " << dynamic_cast<ConstantValue*>(counterValues[i])->getInt();
|
||||
}
|
||||
// 打印元素类型,这个元素类型应该是数组的最终元素类型,例如 i32 或 float
|
||||
// 可以从 globalVarBaseType 逐层剥离得到最终元素类型,但这里简化为直接从值获取
|
||||
printType(counterValues[i]->getType());
|
||||
std::cout << " ";
|
||||
printValue(counterValues[i]);
|
||||
}
|
||||
std::cout << "]";
|
||||
} else {
|
||||
// Scalar initializer
|
||||
if (baseType->isFloat()) {
|
||||
std::cout << "float " << dynamic_cast<ConstantValue*>(global->getByIndex(0))->getFloat();
|
||||
} else {
|
||||
std::cout << "i32 " << dynamic_cast<ConstantValue*>(global->getByIndex(0))->getInt();
|
||||
}
|
||||
// 标量初始化器
|
||||
// 假设标量全局变量的初始化值通过 getByIndex(0) 获取
|
||||
Value* initVal = global->getByIndex(0);
|
||||
printType(initVal->getType()); // 打印标量值的类型
|
||||
std::cout << " ";
|
||||
printValue(initVal); // 打印标量值
|
||||
}
|
||||
|
||||
std::cout << ", align 4" << std::endl;
|
||||
@@ -209,19 +214,19 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kFDiv: std::cout << "fdiv"; break;
|
||||
case Kind::kICmpEQ: std::cout << "icmp eq"; break;
|
||||
case Kind::kICmpNE: std::cout << "icmp ne"; break;
|
||||
case Kind::kICmpLT: std::cout << "icmp slt"; break;
|
||||
case Kind::kICmpLT: std::cout << "icmp slt"; break; // LLVM uses slt/sgt for signed less/greater than
|
||||
case Kind::kICmpGT: std::cout << "icmp sgt"; break;
|
||||
case Kind::kICmpLE: std::cout << "icmp sle"; break;
|
||||
case Kind::kICmpGE: std::cout << "icmp sge"; break;
|
||||
case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break;
|
||||
case Kind::kFCmpNE: std::cout << "fcmp one"; break;
|
||||
case Kind::kFCmpLT: std::cout << "fcmp olt"; break;
|
||||
case Kind::kFCmpGT: std::cout << "fcmp ogt"; break;
|
||||
case Kind::kFCmpLE: std::cout << "fcmp ole"; break;
|
||||
case Kind::kFCmpGE: std::cout << "fcmp oge"; break;
|
||||
case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break; // oeq for ordered equal
|
||||
case Kind::kFCmpNE: std::cout << "fcmp one"; break; // one for ordered not equal
|
||||
case Kind::kFCmpLT: std::cout << "fcmp olt"; break; // olt for ordered less than
|
||||
case Kind::kFCmpGT: std::cout << "fcmp ogt"; break; // ogt for ordered greater than
|
||||
case Kind::kFCmpLE: std::cout << "fcmp ole"; break; // ole for ordered less than or equal
|
||||
case Kind::kFCmpGE: std::cout << "fcmp oge"; break; // oge for ordered greater than or equal
|
||||
case Kind::kAnd: std::cout << "and"; break;
|
||||
case Kind::kOr: std::cout << "or"; break;
|
||||
default: break;
|
||||
default: break; // Should not reach here
|
||||
}
|
||||
|
||||
// Types and operands
|
||||
@@ -238,7 +243,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kNeg:
|
||||
case Kind::kNot:
|
||||
case Kind::kFNeg:
|
||||
case Kind::kFNot:
|
||||
case Kind::kFtoI:
|
||||
case Kind::kBitFtoI:
|
||||
case Kind::kItoF:
|
||||
@@ -250,31 +254,39 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
}
|
||||
|
||||
switch (pInst->getKind()) {
|
||||
case Kind::kNeg: std::cout << "sub "; break;
|
||||
case Kind::kNot: std::cout << "not "; break;
|
||||
case Kind::kFNeg: std::cout << "fneg "; break;
|
||||
case Kind::kFNot: std::cout << "fneg "; break; // FNot not standard, map to fneg
|
||||
case Kind::kFtoI: std::cout << "fptosi "; break;
|
||||
case Kind::kBitFtoI: std::cout << "bitcast "; break;
|
||||
case Kind::kItoF: std::cout << "sitofp "; break;
|
||||
case Kind::kBitItoF: std::cout << "bitcast "; break;
|
||||
default: break;
|
||||
case Kind::kNeg: std::cout << "sub "; break; // integer negation is `sub i32 0, operand`
|
||||
case Kind::kNot: std::cout << "xor "; break; // logical/bitwise NOT is `xor i32 -1, operand` or `xor i1 true, operand`
|
||||
case Kind::kFNeg: std::cout << "fneg "; break; // float negation
|
||||
case Kind::kFtoI: std::cout << "fptosi "; break; // float to signed integer
|
||||
case Kind::kBitFtoI: std::cout << "bitcast "; break; // bitcast float to int
|
||||
case Kind::kItoF: std::cout << "sitofp "; break; // signed integer to float
|
||||
case Kind::kBitItoF: std::cout << "bitcast "; break; // bitcast int to float
|
||||
default: break; // Should not reach here
|
||||
}
|
||||
|
||||
printType(unyInst->getType());
|
||||
printType(unyInst->getOperand()->getType()); // Print operand type
|
||||
std::cout << " ";
|
||||
|
||||
// Special handling for negation
|
||||
if (pInst->getKind() == Kind::kNeg || pInst->getKind() == Kind::kNot) {
|
||||
std::cout << "i32 0, ";
|
||||
// Special handling for integer negation and logical NOT
|
||||
if (pInst->getKind() == Kind::kNeg) {
|
||||
std::cout << "0, "; // for 'sub i32 0, operand'
|
||||
} else if (pInst->getKind() == Kind::kNot) {
|
||||
// For logical NOT (i1 -> i1), use 'xor i1 true, operand'
|
||||
// For bitwise NOT (i32 -> i32), use 'xor i32 -1, operand'
|
||||
if (unyInst->getOperand()->getType()->isInt()) { // Assuming i32 for bitwise NOT
|
||||
std::cout << "NOT, "; // or specific bitmask for NOT
|
||||
} else { // Assuming i1 for logical NOT
|
||||
std::cout << "true, ";
|
||||
}
|
||||
}
|
||||
|
||||
printValue(pInst->getOperand(0));
|
||||
|
||||
// For bitcast, need to specify destination type
|
||||
if (pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) {
|
||||
// For type conversions (fptosi, sitofp, bitcast), need to specify destination type
|
||||
if (pInst->getKind() == Kind::kFtoI || pInst->getKind() == Kind::kItoF ||
|
||||
pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) {
|
||||
std::cout << " to ";
|
||||
printType(unyInst->getType());
|
||||
printType(unyInst->getType()); // Print result type
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
@@ -289,7 +301,7 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
}
|
||||
|
||||
std::cout << "call ";
|
||||
printType(callInst->getType());
|
||||
printType(callInst->getType()); // Return type of the call
|
||||
std::cout << " @" << function->getName() << "(";
|
||||
|
||||
auto params = callInst->getArguments();
|
||||
@@ -297,9 +309,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
for (auto ¶m : params) {
|
||||
if (!first) std::cout << ", ";
|
||||
first = false;
|
||||
printType(param->getValue()->getType());
|
||||
printType(param->getValue()->getType()); // Type of argument
|
||||
std::cout << " ";
|
||||
printValue(param->getValue());
|
||||
printValue(param->getValue()); // Value of argument
|
||||
}
|
||||
|
||||
std::cout << ")" << std::endl;
|
||||
@@ -307,7 +319,7 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
|
||||
case Kind::kCondBr: {
|
||||
auto condBrInst = dynamic_cast<CondBrInst *>(pInst);
|
||||
std::cout << "br i1 ";
|
||||
std::cout << "br i1 "; // Condition type should be i1
|
||||
printValue(condBrInst->getCondition());
|
||||
std::cout << ", label %" << condBrInst->getThenBlock()->getName();
|
||||
std::cout << ", label %" << condBrInst->getElseBlock()->getName();
|
||||
@@ -337,14 +349,17 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
|
||||
std::cout << "%" << allocaInst->getName() << " = alloca ";
|
||||
|
||||
auto baseType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
|
||||
printType(baseType);
|
||||
// AllocaInst 的类型现在应该是一个 PointerType,指向正确的 ArrayType 或 ScalarType
|
||||
// 例如:alloca i32, align 4 或者 alloca [10 x i32], align 4
|
||||
auto allocatedType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
|
||||
printType(allocatedType);
|
||||
|
||||
if (allocaInst->getNumDims() > 0) {
|
||||
// 仍然打印维度信息,如果存在的话
|
||||
if (allocaInst->getNumDims() > 0) {
|
||||
std::cout << ", ";
|
||||
for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
printType(Type::getIntType()); // 维度大小通常是 i32 类型
|
||||
std::cout << " ";
|
||||
printValue(allocaInst->getDim(i));
|
||||
}
|
||||
@@ -356,70 +371,74 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kLoad: {
|
||||
auto loadInst = dynamic_cast<LoadInst *>(pInst);
|
||||
std::cout << "%" << loadInst->getName() << " = load ";
|
||||
printType(loadInst->getType());
|
||||
printType(loadInst->getType()); // 加载的结果类型
|
||||
std::cout << ", ";
|
||||
printType(loadInst->getPointer()->getType());
|
||||
printType(loadInst->getPointer()->getType()); // 指针类型
|
||||
std::cout << " ";
|
||||
printValue(loadInst->getPointer());
|
||||
printValue(loadInst->getPointer()); // 要加载的地址
|
||||
|
||||
// 仍然打印索引信息,如果存在的话
|
||||
if (loadInst->getNumIndices() > 0) {
|
||||
std::cout << ", ";
|
||||
std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
|
||||
for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
std::cout << " ";
|
||||
printValue(loadInst->getIndex(i));
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(loadInst->getIndex(i)->getType());
|
||||
std::cout << " ";
|
||||
printValue(loadInst->getIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << ", align 4" << std::endl;
|
||||
} break;
|
||||
|
||||
case Kind::kLa: {
|
||||
auto laInst = dynamic_cast<LaInst *>(pInst);
|
||||
std::cout << "%" << laInst->getName() << " = getelementptr inbounds ";
|
||||
|
||||
auto ptrType = dynamic_cast<PointerType*>(laInst->getPointer()->getType());
|
||||
printType(ptrType->getBaseType());
|
||||
std::cout << ", ";
|
||||
printType(laInst->getPointer()->getType());
|
||||
std::cout << " ";
|
||||
printValue(laInst->getPointer());
|
||||
std::cout << ", ";
|
||||
|
||||
for (size_t i = 0; i < laInst->getNumIndices(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
std::cout << " ";
|
||||
printValue(laInst->getIndex(i));
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
|
||||
case Kind::kStore: {
|
||||
auto storeInst = dynamic_cast<StoreInst *>(pInst);
|
||||
std::cout << "store ";
|
||||
printType(storeInst->getValue()->getType());
|
||||
printType(storeInst->getValue()->getType()); // 要存储的值的类型
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getValue());
|
||||
printValue(storeInst->getValue()); // 要存储的值
|
||||
std::cout << ", ";
|
||||
printType(storeInst->getPointer()->getType());
|
||||
printType(storeInst->getPointer()->getType()); // 目标指针的类型
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getPointer());
|
||||
printValue(storeInst->getPointer()); // 目标地址
|
||||
|
||||
// 仍然打印索引信息,如果存在的话
|
||||
if (storeInst->getNumIndices() > 0) {
|
||||
std::cout << ", ";
|
||||
std::cout << ", indices "; // 或者其他分隔符
|
||||
for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(Type::getIntType());
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getIndex(i));
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(storeInst->getIndex(i)->getType());
|
||||
std::cout << " ";
|
||||
printValue(storeInst->getIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << ", align 4" << std::endl;
|
||||
} break;
|
||||
|
||||
case Kind::kGetElementPtr: { // 新增:GetElementPtrInst 打印
|
||||
auto gepInst = dynamic_cast<GetElementPtrInst*>(pInst);
|
||||
std::cout << "%" << gepInst->getName() << " = getelementptr inbounds "; // 假设总是 inbounds
|
||||
|
||||
// GEP 的第一个操作数是基指针,其类型是一个指向聚合类型的指针
|
||||
// 第一个参数是基指针所指向的聚合类型的类型 (e.g., [10 x i32])
|
||||
auto basePtrType = dynamic_cast<PointerType*>(gepInst->getBasePointer()->getType());
|
||||
printType(basePtrType->getBaseType()); // 打印基指针指向的类型
|
||||
|
||||
std::cout << ", ";
|
||||
printType(gepInst->getBasePointer()->getType()); // 打印基指针自身的类型 (e.g., [10 x i32]*)
|
||||
std::cout << " ";
|
||||
printValue(gepInst->getBasePointer()); // 打印基指针
|
||||
|
||||
// 打印所有索引
|
||||
for (auto indexVal : gepInst->getIndices()) { // 使用 getIndices() 迭代器
|
||||
std::cout << ", ";
|
||||
printType(indexVal->getValue()->getType()); // 打印索引的类型 (通常是 i32)
|
||||
std::cout << " ";
|
||||
printValue(indexVal->getValue()); // 打印索引值
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
|
||||
case Kind::kMemset: {
|
||||
auto memsetInst = dynamic_cast<MemsetInst *>(pInst);
|
||||
@@ -433,51 +452,40 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
printValue(memsetInst->getValue());
|
||||
std::cout << ", i32 ";
|
||||
printValue(memsetInst->getSize());
|
||||
std::cout << ", i1 false)" << std::endl;
|
||||
std::cout << ", i1 false)" << std::endl; // alignment for memset is typically i1
|
||||
} break;
|
||||
|
||||
case Kind::kPhi: {
|
||||
auto phiInst = dynamic_cast<PhiInst *>(pInst);
|
||||
printValue(phiInst->getOperand(0));
|
||||
std::cout << " = phi ";
|
||||
printType(phiInst->getType());
|
||||
// Phi 指令的名称通常是结果变量
|
||||
std::cout << "%" << phiInst->getName() << " = phi ";
|
||||
printType(phiInst->getType()); // Phi 结果类型
|
||||
|
||||
for (unsigned i = 1; i < phiInst->getNumOperands(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
// Phi 指令的操作数是成对的 [value, basic_block]
|
||||
// 这里假设 getOperands() 返回的是 (val1, block1, val2, block2...)
|
||||
// 如果你的 PhiInst 存储方式是 getIncomingValues() 和 getIncomingBlocks(),请相应调整
|
||||
// LLVM IR 格式: phi type [value1, block1], [value2, block2]
|
||||
bool firstPair = true;
|
||||
for (unsigned i = 0; i < phiInst->getNumOperands() / 2; ++i) { // 遍历成对的操作数
|
||||
if (!firstPair) std::cout << ", ";
|
||||
firstPair = false;
|
||||
std::cout << "[ ";
|
||||
printValue(phiInst->getOperand(i));
|
||||
printValue(phiInst->getOperand(i * 2)); // value
|
||||
std::cout << ", %";
|
||||
printValue(phiInst->getOperand(i * 2 + 1)); // block
|
||||
std::cout << " ]";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
|
||||
case Kind::kGetSubArray: {
|
||||
auto getSubArrayInst = dynamic_cast<GetSubArrayInst *>(pInst);
|
||||
std::cout << "%" << getSubArrayInst->getName() << " = getelementptr inbounds ";
|
||||
|
||||
auto ptrType = dynamic_cast<PointerType*>(getSubArrayInst->getFatherArray()->getType());
|
||||
printType(ptrType->getBaseType());
|
||||
std::cout << ", ";
|
||||
printType(getSubArrayInst->getFatherArray()->getType());
|
||||
std::cout << " ";
|
||||
printValue(getSubArrayInst->getFatherArray());
|
||||
std::cout << ", ";
|
||||
bool firstIndex = true;
|
||||
for (auto &index : getSubArrayInst->getIndices()) {
|
||||
if (!firstIndex) std::cout << ", ";
|
||||
firstIndex = false;
|
||||
printType(Type::getIntType());
|
||||
std::cout << " ";
|
||||
printValue(index->getValue());
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
// 以下两个 Kind 应该删除或替换为 kGEP
|
||||
// case Kind::kLa: { /* REMOVED */ } break;
|
||||
// case Kind::kGetSubArray: { /* REMOVED */ } break;
|
||||
|
||||
default:
|
||||
assert(false && "Unsupported instruction kind");
|
||||
assert(false && "Unsupported instruction kind in SysYPrinter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
} // namespace sysy
|
||||
Reference in New Issue
Block a user