// SysYIRGenerator.cpp // TODO:类型转换及其检查 // TODO:sysy库函数处理 // TODO:数组处理 // TODO:对while、continue、break的测试 #include "IR.h" #include #include #include #include #include #include #include "SysYIRGenerator.h" using namespace std; namespace sysy { Type* SysYIRGenerator::buildArrayType(Type* baseType, const std::vector& dims){ Type* currentType = baseType; // 从最内层维度开始构建 ArrayType // 例如对于 int arr[2][3],先处理 [3],再处理 [2] // 注意:SysY 的 dims 是从最外层到最内层,所以我们需要反向迭代 // 或者调整逻辑,使得从内到外构建 ArrayType // 假设 dims 列表是 [dim1, dim2, dim3...] (例如 [2, 3] for int[2][3]) // 我们需要从最内层维度开始向外构建 ArrayType for (int i = dims.size() - 1; i >= 0; --i) { // 维度大小必须是常量,否则无法构建 ArrayType ConstantInteger* constDim = dynamic_cast(dims[i]); if (constDim == nullptr) { // 如果维度不是常量,可能需要特殊处理,例如将其视为指针 // 对于函数参数 int arr[] 这种,第一个维度可以为未知 // 在这里,我们假设所有声明的数组维度都是常量 assert(false && "Array dimension must be a constant integer!"); return nullptr; } unsigned dimSize = constDim->getInt(); currentType = Type::getArrayType(currentType, dimSize); } return currentType; } Value* SysYIRGenerator::getGEPAddressInst(Value* basePointer, const std::vector& indices) { // 检查 basePointer 是否为指针类型 if (!basePointer->getType()->isPointer()) { assert(false && "GEP base pointer must be a pointer type!"); } // 获取基指针所指向的实际类型 (例如 int* 指向 int, int[2][3]* 指向 int[2][3]) Type* currentElementType = basePointer->getType()->as()->getBaseType(); std::vector actualGEPIndices; // GEP 指令的第一个索引通常是0,用于“跳过”基指针指向的聚合类型本身,直接指向其第一个元素。 // 例如,对于 AllocaInst 返回的 `int[2][3]*`,第一个 `0` 索引表示从数组的开始而不是指针本身开始索引。 actualGEPIndices.push_back(ConstantInteger::get(0)); // 将用户提供的索引添加到 GEP 操作数中 for (Value* index : indices) { actualGEPIndices.push_back(index); } // 根据索引链计算最终的元素类型 Type* finalTargetType = currentElementType; // 遍历用户提供的索引(不包括我们添加的第一个0),逐步确定 GEP 的最终结果类型 // 每个索引都“深入”一个维度 for (int i = 0; i < indices.size(); ++i) { // 这里遍历的是用户提供的索引 if (finalTargetType && finalTargetType->isArray()) { finalTargetType = finalTargetType->as()->getElementType(); } else { // 如果索引链还在继续,但当前类型已经不是数组或聚合类型,这通常是一个错误 // 或者表示访问的是标量,后续索引无效。此时,finalTargetType 已经是最终的标量类型,不能再深入。 // 例如,对 int arr[5]; 访问 arr[i][j] (j 是多余的),这里会停止类型推断。 break; } } // GEP 的结果总是指针类型,指向最终计算出的元素 Type* gepResultType = Type::getPointerType(finalTargetType); // 创建 GEP 指令。假设 builder.createGetElementPtrInst 的签名为 // (Type* resultType, Value* basePointer, const std::vector& indices) return builder.createGetElementPtrInst(basePointer, actualGEPIndices); } /* * @brief: visit compUnit * @details: * compUnit: (globalDecl | funcDef)+; */ std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext *ctx) { // create the IR module auto pModule = new Module(); assert(pModule); module.reset(pModule); // SymbolTable::ModuleScope scope(symbols_table); Utils::initExternalFunction(pModule, &builder); pModule->enterNewScope(); visitChildren(ctx); pModule->leaveScope(); return pModule; } std::any SysYIRGenerator::visitGlobalConstDecl(SysYParser::GlobalConstDeclContext *ctx){ auto constDecl = ctx->constDecl(); Type* type = std::any_cast(visitBType(constDecl->bType())); for (const auto &constDef : constDecl->constDef()) { std::vector dims = {}; std::string name = constDef->Ident()->getText(); auto constExps = constDef->constExp(); if (!constExps.empty()) { for (const auto &constExp : constExps) { dims.push_back(std::any_cast(visitConstExp(constExp))); } } ArrayValueTree* root = std::any_cast(constDef->constInitVal()->accept(this)); ValueCounter values; Utils::tree2Array(type, root, dims, dims.size(), values, &builder); delete root; // 创建全局常量变量,并更新符号表 module->createConstVar(name, Type::getPointerType(type), values, dims); } return std::any(); } std::any SysYIRGenerator::visitGlobalVarDecl(SysYParser::GlobalVarDeclContext *ctx) { auto varDecl = ctx->varDecl(); Type* type = std::any_cast(visitBType(varDecl->bType())); for (const auto &varDef : varDecl->varDef()) { std::vector dims = {}; std::string name = varDef->Ident()->getText(); auto constExps = varDef->constExp(); if (!constExps.empty()) { for (const auto &constExp : constExps) { dims.push_back(std::any_cast(visitConstExp(constExp))); } } ValueCounter values = {}; if (varDef->initVal() != nullptr) { ArrayValueTree* root = std::any_cast(varDef->initVal()->accept(this)); Utils::tree2Array(type, root, dims, dims.size(), values, &builder); delete root; } // 创建全局变量,并更新符号表 module->createGlobalValue(name, Type::getPointerType(type), dims, values); } return std::any(); } std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx){ Type* type = std::any_cast(visitBType(ctx->bType())); for (const auto constDef : ctx->constDef()) { std::vector dims = {}; std::string name = constDef->Ident()->getText(); auto constExps = constDef->constExp(); if (!constExps.empty()) { for (const auto constExp : constExps) { dims.push_back(std::any_cast(visitConstExp(constExp))); } } ArrayValueTree* root = std::any_cast(constDef->constInitVal()->accept(this)); ValueCounter values; Utils::tree2Array(type, root, dims, dims.size(), values, &builder); delete root; module->createConstVar(name, Type::getPointerType(type), values, dims); } return 0; } std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) { Type* type = std::any_cast(visitBType(ctx->bType())); for (const auto varDef : ctx->varDef()) { std::vector dims = {}; std::string name = varDef->Ident()->getText(); auto constExps = varDef->constExp(); if (!constExps.empty()) { for (const auto &constExp : constExps) { dims.push_back(std::any_cast(visitConstExp(constExp))); } } Type* variableType = type; if (!dims.empty()) { // 如果有维度,说明是数组 variableType = buildArrayType(type, dims); // 构建完整的 ArrayType } // 对于数组,alloca 的类型将是指针指向数组类型,例如 `int[2][3]*` // 对于标量,alloca 的类型将是指针指向标量类型,例如 `int*` AllocaInst* alloca = builder.createAllocaInst(Type::getPointerType(type), dims, name); if (varDef->initVal() != nullptr) { ValueCounter values; ArrayValueTree* root = std::any_cast(varDef->initVal()->accept(this)); Utils::tree2Array(type, root, dims, dims.size(), values, &builder); delete root; if (dims.empty()) { // 标量变量初始化 builder.createStoreInst(values.getValue(0), alloca); } else { // 数组变量初始化 const std::vector &counterValues = values.getValues(); int numElements = 1; std::vector dimSizes; for (Value *dimVal : dims) { if (ConstantInteger *constInt = dynamic_cast(dimVal)) { int dimSize = constInt->getInt(); numElements *= dimSize; dimSizes.push_back(dimSize); } // TODO else 错误处理:数组维度必须是常量(对于静态分配) } unsigned int elementSizeInBytes = type->getSize(); unsigned int totalSizeInBytes = numElements * elementSizeInBytes; bool allValuesAreZero = false; if (counterValues.empty()) { allValuesAreZero = true; } else { allValuesAreZero = true; for (Value *val : counterValues){ if (ConstantInteger *constInt = dynamic_cast(val)){ if (constInt->getInt() != 0){ allValuesAreZero = false; break; } } else{ allValuesAreZero = false; break; } } } if (allValuesAreZero) { builder.createMemsetInst( alloca, ConstantInteger::get(0), ConstantInteger::get(totalSizeInBytes), ConstantInteger::get(0)); } else { for (int k = 0; k < counterValues.size(); ++k) { std::vector currentIndices; int tempLinearIndex = k; // 将线性索引转换为多维索引 for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) { currentIndices.insert(currentIndices.begin(), ConstantInteger::get(static_cast(tempLinearIndex % dimSizes[dimIdx]))); tempLinearIndex /= dimSizes[dimIdx]; } // 计算元素的地址 Value* elementAddress = getGEPAddressInst(alloca, currentIndices); // 生成 store 指令 (假设 createStoreInst 接受 Value* value, Value* pointer) builder.createStoreInst(counterValues[k], elementAddress); } } } } else { // 如果没有显式初始化值,默认对数组进行零初始化 if (!dims.empty()) { // 只有数组才需要默认的零初始化 int numElements = 1; for (Value *dimVal : dims) { if (ConstantInteger *constInt = dynamic_cast(dimVal)) { numElements *= constInt->getInt(); } } unsigned int elementSizeInBytes = type->getSize(); unsigned int totalSizeInBytes = numElements * elementSizeInBytes; builder.createMemsetInst( alloca, ConstantInteger::get(0), ConstantInteger::get(totalSizeInBytes), ConstantInteger::get(0) ); } } module->addVariable(name, alloca); } return std::any(); } std::any SysYIRGenerator::visitBType(SysYParser::BTypeContext *ctx) { return ctx->INT() != nullptr ? Type::getIntType() : Type::getFloatType(); } std::any SysYIRGenerator::visitScalarInitValue(SysYParser::ScalarInitValueContext *ctx) { Value* value = std::any_cast(visitExp(ctx->exp())); ArrayValueTree* result = new ArrayValueTree(); result->setValue(value); return result; } std::any SysYIRGenerator::visitArrayInitValue(SysYParser::ArrayInitValueContext *ctx) { std::vector children; for (const auto &initVal : ctx->initVal()) children.push_back(std::any_cast(initVal->accept(this))); ArrayValueTree* result = new ArrayValueTree(); result->addChildren(children); return result; } std::any SysYIRGenerator::visitConstScalarInitValue(SysYParser::ConstScalarInitValueContext *ctx) { Value* value = std::any_cast(visitConstExp(ctx->constExp())); ArrayValueTree* result = new ArrayValueTree(); result->setValue(value); return result; } std::any SysYIRGenerator::visitConstArrayInitValue(SysYParser::ConstArrayInitValueContext *ctx) { std::vector children; for (const auto &constInitVal : ctx->constInitVal()) children.push_back(std::any_cast(constInitVal->accept(this))); ArrayValueTree* result = new ArrayValueTree(); result->addChildren(children); return result; } std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext *ctx) { if (ctx->INT() != nullptr) return Type::getIntType(); if (ctx->FLOAT() != nullptr) return Type::getFloatType(); return Type::getVoidType(); } std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){ // 更新作用域 module->enterNewScope(); auto name = ctx->Ident()->getText(); std::vector paramTypes; std::vector paramNames; std::vector> paramDims; if (ctx->funcFParams() != nullptr) { auto params = ctx->funcFParams()->funcFParam(); for (const auto ¶m : params) { paramTypes.push_back(std::any_cast(visitBType(param->bType()))); paramNames.push_back(param->Ident()->getText()); std::vector dims = {}; if (!param->LBRACK().empty()) { dims.push_back(ConstantInteger::get(-1)); // 第一个维度不确定 for (const auto &exp : param->exp()) { dims.push_back(std::any_cast(visitExp(exp))); } } paramDims.emplace_back(dims); } } Type* returnType = std::any_cast(visitFuncType(ctx->funcType())); Type* funcType = Type::getFunctionType(returnType, paramTypes); Function* function = module->createFunction(name, funcType); BasicBlock* entry = function->getEntryBlock(); builder.setPosition(entry, entry->end()); for (int i = 0; i < paramTypes.size(); ++i) { AllocaInst* alloca = builder.createAllocaInst(Type::getPointerType(paramTypes[i]), paramDims[i], paramNames[i]); entry->insertArgument(alloca); module->addVariable(paramNames[i], alloca); } // 在处理函数体之前,创建一个新的基本块作为函数体的实际入口 // 这样 entryBB 就可以在完成初始化后跳转到这里 BasicBlock* funcBodyEntry = function->addBasicBlock("funcBodyEntry"); // 从 entryBB 无条件跳转到 funcBodyEntry builder.createUncondBrInst(funcBodyEntry, {}); builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry for (auto item : ctx->blockStmt()->blockItem()) { visitBlockItem(item); } // 如果函数没有显式的返回语句,且返回类型不是 void,则需要添加一个默认的返回值 ReturnInst* retinst = nullptr; retinst = dynamic_cast(builder.getBasicBlock()->terminator()->get()); if (!retinst) { if (returnType->isVoid()) { builder.createReturnInst(); } else if (returnType->isInt()) { builder.createReturnInst(ConstantInteger::get(0)); // 默认返回 0 } else if (returnType->isFloat()) { builder.createReturnInst(ConstantFloating::get(0.0f)); // 默认返回 0.0f } else { assert(false && "Function with no explicit return and non-void type should return a value."); } } module->leaveScope(); return std::any(); } std::any SysYIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext *ctx) { module->enterNewScope(); for (auto item : ctx->blockItem()) visitBlockItem(item); module->leaveScope(); return 0; } std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) { auto lVal = ctx->lValue(); std::string name = lVal->Ident()->getText(); std::vector dims; for (const auto &exp : lVal->exp()) { dims.push_back(std::any_cast(visitExp(exp))); } auto variable = module->getVariable(name); // 获取 AllocaInst 或 GlobalValue Value* value = std::any_cast(visitExp(ctx->exp())); // 右值 if (variable == nullptr) { throw std::runtime_error("Variable " + name + " not found in assignment."); } // 计算最终赋值目标元素的类型 // variable 本身应该是一个指针类型 (例如 int* 或 int[2][3]*) if (!variable->getType()->isPointer()) { assert(false && "Variable to be assigned must be a pointer type!"); return std::any(); } Type* targetElementType = variable->getType()->as()->getBaseType(); // 从基指针指向的类型开始 // 模拟 GEP 路径,根据 dims 确定最终元素的类型 for (int i = 0; i < dims.size(); ++i) { if (targetElementType && targetElementType->isArray()) { targetElementType = targetElementType->as()->getElementType(); } else { break; // 如果不是数组类型但还有索引,或者索引超出维度,则停止推断 } } // 左值右值类型不同处理:根据最终元素类型进行转换 if (targetElementType != value->getType()) { ConstantValue * constValue = dynamic_cast(value); if (constValue != nullptr) { if (targetElementType == Type::getFloatType()) { value = ConstantFloating::get(static_cast(constValue->getInt())); } else { // 假设如果不是浮点型,就是整型 value = ConstantInteger::get(static_cast(constValue->getFloat())); } } else { if (targetElementType == Type::getFloatType()) { value = builder.createIToFInst(value); } else { // 假设如果不是浮点型,就是整型 value = builder.createFtoIInst(value); } } } // 计算目标地址:如果 dims 为空,就是变量本身地址;否则通过 GEP 计算 Value* targetAddress = variable; if (!dims.empty()) { targetAddress = getGEPAddressInst(variable, dims); } builder.createStoreInst(value, targetAddress); return std::any(); } std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) { // labels string stream std::stringstream labelstring; Function * function = builder.getBasicBlock()->getParent(); BasicBlock* thenBlock = new BasicBlock(function); BasicBlock* exitBlock = new BasicBlock(function); if (ctx->stmt().size() > 1) { BasicBlock* elseBlock = new BasicBlock(function); builder.pushTrueBlock(thenBlock); builder.pushFalseBlock(elseBlock); // 访问条件表达式 visitCond(ctx->cond()); builder.popTrueBlock(); builder.popFalseBlock(); labelstring << "if_then.L" << builder.getLabelIndex(); thenBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(thenBlock); builder.setPosition(thenBlock, thenBlock->end()); auto block = dynamic_cast(ctx->stmt(0)); // 如果是块语句,直接访问 // 否则访问语句 if (block != nullptr) { visitBlockStmt(block); } else { module->enterNewScope(); ctx->stmt(0)->accept(this); module->leaveScope(); } builder.createUncondBrInst(exitBlock, {}); BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock); labelstring << "if_else.L" << builder.getLabelIndex(); elseBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(elseBlock); builder.setPosition(elseBlock, elseBlock->end()); block = dynamic_cast(ctx->stmt(1)); if (block != nullptr) { visitBlockStmt(block); } else { module->enterNewScope(); ctx->stmt(1)->accept(this); module->leaveScope(); } builder.createUncondBrInst(exitBlock, {}); BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock); labelstring << "if_exit.L" << builder.getLabelIndex(); exitBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(exitBlock); builder.setPosition(exitBlock, exitBlock->end()); } else { builder.pushTrueBlock(thenBlock); builder.pushFalseBlock(exitBlock); visitCond(ctx->cond()); builder.popTrueBlock(); builder.popFalseBlock(); labelstring << "if_then.L" << builder.getLabelIndex(); thenBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(thenBlock); builder.setPosition(thenBlock, thenBlock->end()); auto block = dynamic_cast(ctx->stmt(0)); if (block != nullptr) { visitBlockStmt(block); } else { module->enterNewScope(); ctx->stmt(0)->accept(this); module->leaveScope(); } builder.createUncondBrInst(exitBlock, {}); BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock); labelstring << "if_exit.L" << builder.getLabelIndex(); exitBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(exitBlock); builder.setPosition(exitBlock, exitBlock->end()); } return std::any(); } std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) { // while structure: // curblock -> headBlock -> bodyBlock -> exitBlock BasicBlock* curBlock = builder.getBasicBlock(); Function* function = builder.getBasicBlock()->getParent(); std::stringstream labelstring; labelstring << "while_head.L" << builder.getLabelIndex(); BasicBlock *headBlock = function->addBasicBlock(labelstring.str()); labelstring.str(""); builder.createUncondBrInst(headBlock, {}); BasicBlock::conectBlocks(curBlock, headBlock); builder.setPosition(headBlock, headBlock->end()); BasicBlock* bodyBlock = new BasicBlock(function); BasicBlock* exitBlock = new BasicBlock(function); builder.pushTrueBlock(bodyBlock); builder.pushFalseBlock(exitBlock); // 访问条件表达式 visitCond(ctx->cond()); builder.popTrueBlock(); builder.popFalseBlock(); labelstring << "while_body.L" << builder.getLabelIndex(); bodyBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(bodyBlock); builder.setPosition(bodyBlock, bodyBlock->end()); builder.pushBreakBlock(exitBlock); builder.pushContinueBlock(headBlock); auto block = dynamic_cast(ctx->stmt()); if( block != nullptr) { visitBlockStmt(block); } else { module->enterNewScope(); ctx->stmt()->accept(this); module->leaveScope(); } builder.createUncondBrInst(headBlock, {}); BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock); builder.popBreakBlock(); builder.popContinueBlock(); labelstring << "while_exit.L" << builder.getLabelIndex(); exitBlock->setName(labelstring.str()); labelstring.str(""); function->addBasicBlock(exitBlock); builder.setPosition(exitBlock, exitBlock->end()); return std::any(); } std::any SysYIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext *ctx) { BasicBlock* breakBlock = builder.getBreakBlock(); builder.createUncondBrInst(breakBlock, {}); BasicBlock::conectBlocks(builder.getBasicBlock(), breakBlock); return std::any(); } std::any SysYIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext *ctx) { BasicBlock* continueBlock = builder.getContinueBlock(); builder.createUncondBrInst(continueBlock, {}); BasicBlock::conectBlocks(builder.getBasicBlock(), continueBlock); return std::any(); } std::any SysYIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext *ctx) { Value* returnValue = nullptr; if (ctx->exp() != nullptr) { returnValue = std::any_cast(visitExp(ctx->exp())); } Type* funcType = builder.getBasicBlock()->getParent()->getReturnType(); if (funcType!= returnValue->getType() && returnValue != nullptr) { ConstantValue * constValue = dynamic_cast(returnValue); if (constValue != nullptr) { if (funcType == Type::getFloatType()) { returnValue = ConstantInteger::get(static_cast(constValue->getInt())); } else { returnValue = ConstantFloating::get(static_cast(constValue->getFloat())); } } else { if (funcType == Type::getFloatType()) { returnValue = builder.createIToFInst(returnValue); } else { returnValue = builder.createFtoIInst(returnValue); } } } builder.createReturnInst(returnValue); return std::any(); } // SysYIRGenerator.cpp (修改部分) std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) { std::string name = ctx->Ident()->getText(); User* variable = module->getVariable(name); Value* value = nullptr; if (variable == nullptr) { throw std::runtime_error("Variable " + name + " not found."); } std::vector dims; for (const auto &exp : ctx->exp()) { dims.push_back(std::any_cast(visitExp(exp))); } // 1. 获取变量的声明维度数量 unsigned declaredNumDims = 0; if (AllocaInst* alloc = dynamic_cast(variable)) { declaredNumDims = alloc->getNumDims(); } else if (GlobalValue* glob = dynamic_cast(variable)) { declaredNumDims = glob->getNumDims(); } else if (ConstantVariable* constV = dynamic_cast(variable)) { declaredNumDims = constV->getNumDims(); } // 2. 处理常量变量 (ConstantVariable) 且所有索引都是常量的情况 ConstantVariable* constVar = dynamic_cast(variable); if (constVar != nullptr) { bool allIndicesConstant = true; for (const auto &dim : dims) { if (dynamic_cast(dim) == nullptr) { allIndicesConstant = false; break; } } if (allIndicesConstant) { // 如果是常量变量且所有索引都是常量,直接通过 getByIndices 获取编译时值 // 这个方法会根据索引深度返回最终的标量值或指向子数组的指针 (作为 ConstantValue/Variable) return constVar->getByIndices(dims); } } // 3. 处理可变变量 (AllocaInst/GlobalValue) 或带非常量索引的常量变量 // 这里区分标量访问和数组元素/子数组访问 // 检查是否是访问标量变量本身(没有索引,且声明维度为0) if (dims.empty() && declaredNumDims == 0) { // 对于标量变量,直接加载其值。 // variable 本身就是指向标量的指针 (e.g., int* %a) if (dynamic_cast(variable) || dynamic_cast(variable)) { value = builder.createLoadInst(variable); } else { // 如果走到这里且不是AllocaInst/GlobalValue,但dims为空且declaredNumDims为0, // 且又不是ConstantVariable (前面已处理),则可能是错误情况。 assert(false && "Unhandled scalar variable type in LValue access."); return static_cast(nullptr); } } else { // 访问数组元素或子数组(有索引,或变量本身是数组/多维指针) Value* targetAddress = nullptr; // GEP 的基指针就是变量本身(它是一个指向内存的指针) if (dynamic_cast(variable) || dynamic_cast(variable) || (constVar != nullptr)) { // 允许对 ConstantVariable (如果它代表全局数组常量) 进行 GEP targetAddress = getGEPAddressInst(variable, dims); } else { // 其他情况(例如尝试对非指针类型或不支持的 LValue 进行 GEP)应报错 assert(false && "LValue variable type not supported for GEP or dynamic load."); return static_cast(nullptr); } // 现在 targetAddress 持有元素或子数组的地址。 // 需要判断是加载值,还是返回子数组的地址。 // 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址 if (dims.size() < declaredNumDims) { value = targetAddress; } else { // 否则,表示访问的是最终的标量元素,加载其值 // 假设 createLoadInst 接受 Value* pointer value = builder.createLoadInst(targetAddress); } } return value; } std::any SysYIRGenerator::visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) { if (ctx->exp() != nullptr) return visitExp(ctx->exp()); if (ctx->lValue() != nullptr) return visitLValue(ctx->lValue()); if (ctx->number() != nullptr) return visitNumber(ctx->number()); if (ctx->string() != nullptr) { cout << "String literal not supported in SysYIRGenerator." << endl; } return visitNumber(ctx->number()); } std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext *ctx) { if (ctx->ILITERAL() != nullptr) { int value = std::stol(ctx->ILITERAL()->getText(), nullptr, 0); return static_cast(ConstantInteger::get(value)); } else if (ctx->FLITERAL() != nullptr) { float value = std::stof(ctx->FLITERAL()->getText()); return static_cast(ConstantFloating::get(value)); } throw std::runtime_error("Unknown number type."); return std::any(); // 不会到达这里 } std::any SysYIRGenerator::visitCall(SysYParser::CallContext *ctx) { std::string funcName = ctx->Ident()->getText(); Function *function = module->getFunction(funcName); if (function == nullptr) { function = module->getExternalFunction(funcName); if (function == nullptr) { std::cout << "The function " << funcName << " no defined." << std::endl; assert(function); } } std::vector args = {}; if (funcName == "starttime" || funcName == "stoptime") { // 如果是starttime或stoptime函数 // TODO: 这里需要处理starttime和stoptime函数的参数 // args.emplace_back() } else { if (ctx->funcRParams() != nullptr) { args = std::any_cast>(visitFuncRParams(ctx->funcRParams())); } auto params = function->getEntryBlock()->getArguments(); for (int i = 0; i < args.size(); i++) { // 参数类型转换 if (params[i]->getType() != args[i]->getType() && (params[i]->getNumDims() != 0 || params[i]->getType()->as()->getBaseType() != args[i]->getType())) { ConstantValue * constValue = dynamic_cast(args[i]); if (constValue != nullptr) { if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) { args[i] = ConstantInteger::get(static_cast(constValue->getInt())); } else { args[i] = ConstantFloating::get(static_cast(constValue->getFloat())); } } else { if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) { args[i] = builder.createIToFInst(args[i]); } else { args[i] = builder.createFtoIInst(args[i]); } } } } } return static_cast(builder.createCallInst(function, args)); } std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext *ctx) { if (ctx->primaryExp() != nullptr) return visitPrimaryExp(ctx->primaryExp()); if (ctx->call() != nullptr) return visitCall(ctx->call()); Value* value = std::any_cast(visitUnaryExp(ctx->unaryExp())); Value* result = value; if (ctx->unaryOp()->SUB() != nullptr) { ConstantValue * constValue = dynamic_cast(value); if (constValue != nullptr) { if (constValue->isFloat()) { result = ConstantFloating::get(-constValue->getFloat()); } else { result = ConstantInteger::get(-constValue->getInt()); } } else if (value != nullptr) { if (value->getType() == Type::getIntType()) { result = builder.createNegInst(value); } else { result = builder.createFNegInst(value); } } else { std::cout << "UnExp: value is nullptr." << std::endl; assert(false); } } else if (ctx->unaryOp()->NOT() != nullptr) { auto constValue = dynamic_cast(value); if (constValue != nullptr) { if (constValue->isFloat()) { result = ConstantFloating::get(1 - (constValue->getFloat() != 0.0F ? 1 : 0)); } else { result = ConstantInteger::get(1 - (constValue->getInt() != 0 ? 1 : 0)); } } else if (value != nullptr) { if (value->getType() == Type::getIntType()) { result = builder.createNotInst(value); } else { result = builder.createFNotInst(value); } } else { std::cout << "UnExp: value is nullptr." << std::endl; assert(false); } } return result; } std::any SysYIRGenerator::visitFuncRParams(SysYParser::FuncRParamsContext *ctx) { std::vector params; for (const auto &exp : ctx->exp()) params.push_back(std::any_cast(visitExp(exp))); return params; } std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext *ctx) { Value * result = std::any_cast(visitUnaryExp(ctx->unaryExp(0))); for (int i = 1; i < ctx->unaryExp().size(); i++) { auto opNode = dynamic_cast(ctx->children[2*i-1]); int opType = opNode->getSymbol()->getType(); Value* operand = std::any_cast(visitUnaryExp(ctx->unaryExp(i))); Type* resultType = result->getType(); Type* operandType = operand->getType(); Type* floatType = Type::getFloatType(); if (resultType == floatType || operandType == floatType) { // 如果有一个操作数是浮点数,则将两个操作数都转换为浮点数 if (operandType != floatType) { ConstantValue * constValue = dynamic_cast(operand); if (constValue != nullptr) operand = ConstantFloating::get(static_cast(constValue->getInt())); else operand = builder.createIToFInst(operand); } else if (resultType != floatType) { ConstantValue* constResult = dynamic_cast(result); if (constResult != nullptr) result = ConstantFloating::get(static_cast(constResult->getInt())); else result = builder.createIToFInst(result); } ConstantValue* constResult = dynamic_cast(result); ConstantValue* constOperand = dynamic_cast(operand); if (opType == SysYParser::MUL) { if ((constOperand != nullptr) && (constResult != nullptr)) { result = ConstantFloating::get(constResult->getFloat() * constOperand->getFloat()); } else { result = builder.createFMulInst(result, operand); } } else if (opType == SysYParser::DIV) { if ((constOperand != nullptr) && (constResult != nullptr)) { result = ConstantFloating::get(constResult->getFloat() / constOperand->getFloat()); } else { result = builder.createFDivInst(result, operand); } } else { // float类型的取模操作不允许 std::cout << "MulExp: float type mod operation is not allowed." << std::endl; assert(false); } } else { ConstantValue * constResult = dynamic_cast(result); ConstantValue * constOperand = dynamic_cast(operand); if (opType == SysYParser::MUL) { if ((constOperand != nullptr) && (constResult != nullptr)) result = ConstantInteger::get(constResult->getInt() * constOperand->getInt()); else result = builder.createMulInst(result, operand); } else if (opType == SysYParser::DIV) { if ((constOperand != nullptr) && (constResult != nullptr)) result = ConstantInteger::get(constResult->getInt() / constOperand->getInt()); else result = builder.createDivInst(result, operand); } else { if ((constOperand != nullptr) && (constResult != nullptr)) result = ConstantInteger::get(constResult->getInt() % constOperand->getInt()); else result = builder.createRemInst(result, operand); } } } return result; } std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext *ctx) { Value* result = std::any_cast(visitMulExp(ctx->mulExp(0))); for (int i = 1; i < ctx->mulExp().size(); i++) { auto opNode = dynamic_cast(ctx->children[2*i-1]); int opType = opNode->getSymbol()->getType(); Value* operand = std::any_cast(visitMulExp(ctx->mulExp(i))); Type* resultType = result->getType(); Type* operandType = operand->getType(); Type* floatType = Type::getFloatType(); if (resultType == floatType || operandType == floatType) { // 类型转换 if (operandType != floatType) { ConstantValue * constOperand = dynamic_cast(operand); if (constOperand != nullptr) operand = ConstantFloating::get(static_cast(constOperand->getInt())); else operand = builder.createIToFInst(operand); } else if (resultType != floatType) { ConstantValue * constResult = dynamic_cast(result); if (constResult != nullptr) result = ConstantFloating::get(static_cast(constResult->getInt())); else result = builder.createIToFInst(result); } ConstantValue * constResult = dynamic_cast(result); ConstantValue * constOperand = dynamic_cast(operand); if (opType == SysYParser::ADD) { if ((constResult != nullptr) && (constOperand != nullptr)) result = ConstantFloating::get(constResult->getFloat() + constOperand->getFloat()); else result = builder.createFAddInst(result, operand); } else { if ((constResult != nullptr) && (constOperand != nullptr)) result = ConstantFloating::get(constResult->getFloat() - constOperand->getFloat()); else result = builder.createFSubInst(result, operand); } } else { ConstantValue * constResult = dynamic_cast(result); ConstantValue * constOperand = dynamic_cast(operand); if (opType == SysYParser::ADD) { if ((constResult != nullptr) && (constOperand != nullptr)) result = ConstantInteger::get(constResult->getInt() + constOperand->getInt()); else result = builder.createAddInst(result, operand); } else { if ((constResult != nullptr) && (constOperand != nullptr)) result = ConstantInteger::get(constResult->getInt() - constOperand->getInt()); else result = builder.createSubInst(result, operand); } } } return result; } std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext *ctx) { Value* result = std::any_cast(visitAddExp(ctx->addExp(0))); for (int i = 1; i < ctx->addExp().size(); i++) { auto opNode = dynamic_cast(ctx->children[2*i-1]); int opType = opNode->getSymbol()->getType(); Value* operand = std::any_cast(visitAddExp(ctx->addExp(i))); Type* resultType = result->getType(); Type* operandType = operand->getType(); ConstantValue* constResult = dynamic_cast(result); ConstantValue* constOperand = dynamic_cast(operand); // 常量比较 if ((constResult != nullptr) && (constOperand != nullptr)) { auto operand1 = constResult->isFloat() ? constResult->getFloat() : constResult->getInt(); auto operand2 = constOperand->isFloat() ? constOperand->getFloat() : constOperand->getInt(); if (opType == SysYParser::LT) result = ConstantInteger::get(operand1 < operand2 ? 1 : 0); else if (opType == SysYParser::GT) result = ConstantInteger::get(operand1 > operand2 ? 1 : 0); else if (opType == SysYParser::LE) result = ConstantInteger::get(operand1 <= operand2 ? 1 : 0); else if (opType == SysYParser::GE) result = ConstantInteger::get(operand1 >= operand2 ? 1 : 0); else assert(false); } else { Type* resultType = result->getType(); Type* operandType = operand->getType(); Type* floatType = Type::getFloatType(); // 浮点数处理 if (resultType == floatType || operandType == floatType) { if (resultType != floatType) { if (constResult != nullptr) result = ConstantFloating::get(static_cast(constResult->getInt())); else result = builder.createIToFInst(result); } if (operandType != floatType) { if (constOperand != nullptr) operand = ConstantFloating::get(static_cast(constOperand->getInt())); else operand = builder.createIToFInst(operand); } if (opType == SysYParser::LT) result = builder.createFCmpLTInst(result, operand); else if (opType == SysYParser::GT) result = builder.createFCmpGTInst(result, operand); else if (opType == SysYParser::LE) result = builder.createFCmpLEInst(result, operand); else if (opType == SysYParser::GE) result = builder.createFCmpGEInst(result, operand); else assert(false); } else { // 整数处理 if (opType == SysYParser::LT) result = builder.createICmpLTInst(result, operand); else if (opType == SysYParser::GT) result = builder.createICmpGTInst(result, operand); else if (opType == SysYParser::LE) result = builder.createICmpLEInst(result, operand); else if (opType == SysYParser::GE) result = builder.createICmpGEInst(result, operand); else assert(false); } } } return result; } std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext *ctx) { Value * result = std::any_cast(visitRelExp(ctx->relExp(0))); for (int i = 1; i < ctx->relExp().size(); i++) { auto opNode = dynamic_cast(ctx->children[2*i-1]); int opType = opNode->getSymbol()->getType(); Value * operand = std::any_cast(visitRelExp(ctx->relExp(i))); ConstantValue* constResult = dynamic_cast(result); ConstantValue* constOperand = dynamic_cast(operand); if ((constResult != nullptr) && (constOperand != nullptr)) { auto operand1 = constResult->isFloat() ? constResult->getFloat() : constResult->getInt(); auto operand2 = constOperand->isFloat() ? constOperand->getFloat() : constOperand->getInt(); if (opType == SysYParser::EQ) result = ConstantInteger::get(operand1 == operand2 ? 1 : 0); else if (opType == SysYParser::NE) result = ConstantInteger::get(operand1 != operand2 ? 1 : 0); else assert(false); } else { Type* resultType = result->getType(); Type* operandType = operand->getType(); Type* floatType = Type::getFloatType(); if (resultType == floatType || operandType == floatType) { if (resultType != floatType) { if (constResult != nullptr) result = ConstantFloating::get(static_cast(constResult->getInt())); else result = builder.createIToFInst(result); } if (operandType != floatType) { if (constOperand != nullptr) operand = ConstantFloating::get(static_cast(constOperand->getInt())); else operand = builder.createIToFInst(operand); } if (opType == SysYParser::EQ) result = builder.createFCmpEQInst(result, operand); else if (opType == SysYParser::NE) result = builder.createFCmpNEInst(result, operand); else assert(false); } else { if (opType == SysYParser::EQ) result = builder.createICmpEQInst(result, operand); else if (opType == SysYParser::NE) result = builder.createICmpNEInst(result, operand); else assert(false); } } } if (ctx->relExp().size() == 1) { ConstantValue * constResult = dynamic_cast(result); // 如果只有一个关系表达式,则将结果转换为0或1 if (constResult != nullptr) { if (constResult->isFloat()) result = ConstantInteger::get(constResult->getFloat() != 0.0F ? 1 : 0); else result = ConstantInteger::get(constResult->getInt() != 0 ? 1 : 0); } } return result; } std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext *ctx){ std::stringstream labelstring; BasicBlock *curBlock = builder.getBasicBlock(); Function *function = builder.getBasicBlock()->getParent(); BasicBlock *trueBlock = builder.getTrueBlock(); BasicBlock *falseBlock = builder.getFalseBlock(); auto conds = ctx->eqExp(); for (int i = 0; i < conds.size() - 1; i++) { labelstring << "AND.L" << builder.getLabelIndex(); BasicBlock *newtrueBlock = function->addBasicBlock(labelstring.str()); labelstring.str(""); auto cond = std::any_cast(visitEqExp(ctx->eqExp(i))); builder.createCondBrInst(cond, newtrueBlock, falseBlock, {}, {}); BasicBlock::conectBlocks(curBlock, newtrueBlock); BasicBlock::conectBlocks(curBlock, falseBlock); curBlock = newtrueBlock; builder.setPosition(curBlock, curBlock->end()); } auto cond = std::any_cast(visitEqExp(conds.back())); builder.createCondBrInst(cond, trueBlock, falseBlock, {}, {}); BasicBlock::conectBlocks(curBlock, trueBlock); BasicBlock::conectBlocks(curBlock, falseBlock); return std::any(); } auto SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext *ctx) -> std::any { std::stringstream labelstring; BasicBlock *curBlock = builder.getBasicBlock(); Function *function = curBlock->getParent(); auto conds = ctx->lAndExp(); for (int i = 0; i < conds.size() - 1; i++) { labelstring << "OR.L" << builder.getLabelIndex(); BasicBlock *newFalseBlock = function->addBasicBlock(labelstring.str()); labelstring.str(""); builder.pushFalseBlock(newFalseBlock); visitLAndExp(ctx->lAndExp(i)); builder.popFalseBlock(); builder.setPosition(newFalseBlock, newFalseBlock->end()); } visitLAndExp(conds.back()); return std::any(); } void Utils::tree2Array(Type *type, ArrayValueTree *root, const std::vector &dims, unsigned numDims, ValueCounter &result, IRBuilder *builder) { Value* value = root->getValue(); auto &children = root->getChildren(); // 类型转换 if (value != nullptr) { if (type == value->getType()) { result.push_back(value); } else { if (type == Type::getFloatType()) { ConstantValue* constValue = dynamic_cast(value); if (constValue != nullptr) result.push_back(ConstantFloating::get(static_cast(constValue->getInt()))); else result.push_back(builder->createIToFInst(value)); } else { ConstantValue* constValue = dynamic_cast(value); if (constValue != nullptr) result.push_back(ConstantInteger::get(static_cast(constValue->getFloat()))); else result.push_back(builder->createFtoIInst(value)); } } return; } auto beforeSize = result.size(); for (const auto &child : children) { int begin = result.size(); int newNumDims = 0; for (unsigned i = 0; i < numDims - 1; i++) { auto dim = dynamic_cast(*(dims.rbegin() + i))->getInt(); if (begin % dim == 0) { newNumDims += 1; begin /= dim; } else { break; } } tree2Array(type, child.get(), dims, newNumDims, result, builder); } auto afterSize = result.size(); int blockSize = 1; for (unsigned i = 0; i < numDims; i++) { blockSize *= dynamic_cast(*(dims.rbegin() + i))->getInt(); } int num = blockSize - afterSize + beforeSize; if (num > 0) { if (type == Type::getFloatType()) result.push_back(ConstantFloating::get(0.0F), num); else result.push_back(ConstantInteger::get(0), num); } } void Utils::createExternalFunction( const std::vector ¶mTypes, const std::vector ¶mNames, const std::vector> ¶mDims, Type *returnType, const std::string &funcName, Module *pModule, IRBuilder *pBuilder) { auto funcType = Type::getFunctionType(returnType, paramTypes); auto function = pModule->createExternalFunction(funcName, funcType); auto entry = function->getEntryBlock(); pBuilder->setPosition(entry, entry->end()); for (int i = 0; i < paramTypes.size(); ++i) { auto alloca = pBuilder->createAllocaInst( Type::getPointerType(paramTypes[i]), paramDims[i], paramNames[i]); entry->insertArgument(alloca); // pModule->addVariable(paramNames[i], alloca); } } void Utils::initExternalFunction(Module *pModule, IRBuilder *pBuilder) { std::vector paramTypes; std::vector paramNames; std::vector> paramDims; Type *returnType; std::string funcName; returnType = Type::getIntType(); funcName = "getint"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); funcName = "getch"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); paramTypes.push_back(Type::getIntType()); paramNames.emplace_back("x"); paramDims.push_back(std::vector{ConstantInteger::get(-1)}); funcName = "getarray"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); returnType = Type::getFloatType(); paramTypes.clear(); paramNames.clear(); paramDims.clear(); funcName = "getfloat"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); returnType = Type::getIntType(); paramTypes.push_back(Type::getFloatType()); paramNames.emplace_back("x"); paramDims.push_back(std::vector{ConstantInteger::get(-1)}); funcName = "getfarray"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); returnType = Type::getVoidType(); paramTypes.clear(); paramTypes.push_back(Type::getIntType()); paramDims.clear(); paramDims.emplace_back(); funcName = "putint"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); funcName = "putch"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); paramTypes.clear(); paramTypes.push_back(Type::getIntType()); paramTypes.push_back(Type::getIntType()); paramDims.clear(); paramDims.emplace_back(); paramDims.push_back(std::vector{ConstantInteger::get(-1)}); paramNames.clear(); paramNames.emplace_back("n"); paramNames.emplace_back("a"); funcName = "putarray"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); paramTypes.clear(); paramTypes.push_back(Type::getFloatType()); paramDims.clear(); paramDims.emplace_back(); paramNames.clear(); paramNames.emplace_back("a"); funcName = "putfloat"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); paramTypes.clear(); paramTypes.push_back(Type::getIntType()); paramTypes.push_back(Type::getFloatType()); paramDims.clear(); paramDims.emplace_back(); paramDims.push_back(std::vector{ConstantInteger::get(-1)}); paramNames.clear(); paramNames.emplace_back("n"); paramNames.emplace_back("a"); funcName = "putfarray"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); paramTypes.clear(); paramTypes.push_back(Type::getIntType()); paramDims.clear(); paramDims.emplace_back(); paramNames.clear(); paramNames.emplace_back("__LINE__"); funcName = "starttime"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); paramTypes.clear(); paramTypes.push_back(Type::getIntType()); paramDims.clear(); paramDims.emplace_back(); paramNames.clear(); paramNames.emplace_back("__LINE__"); funcName = "stoptime"; Utils::createExternalFunction(paramTypes, paramNames, paramDims, returnType, funcName, pModule, pBuilder); } } // namespace sysy