diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index afaf24b..40b5f59 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -10,10 +10,9 @@ #include #include #include -using namespace std; #include "SysYIRGenerator.h" - +using namespace std; namespace sysy { /* @@ -130,30 +129,111 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) { delete root; if (dims.empty()) { builder.createStoreInst(values.getValue(0), alloca); - } else { - // 对于多维数组,使用memset初始化 - // 计算每个维度的大小 - // 这里的values.getNumbers()返回的是每个维度的大小 - // 这里的values.getValues()返回的是每个维度对应的值 - // 例如:对于一个二维数组,values.getNumbers()可能是[3, 4],表示3行4列 - // values.getValues()可能是[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - // 对于每个维度,使用memset将对应的值填充到数组中 - // 这里的alloca是一个指向数组的指针 - const std::vector & counterNumbers = values.getNumbers(); - const std::vector & counterValues = values.getValues(); - unsigned begin = 0; - for (size_t i = 0; i < counterNumbers.size(); i++) { - + } 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()) { // 例如 int arr[3] = {}; 或 int arr[3][4] = {}; + allValuesAreZero = true; + } + else { + allValuesAreZero = true; + for (Value *val : counterValues){ + if (ConstantInteger *constInt = dynamic_cast(val)){ + if (constInt->getInt() != 0){ + allValuesAreZero = false; + break; + } + } + else{ + // 如果值不是常量,我们通常不能确定它是否为零,所以不进行 memset 优化 + allValuesAreZero = false; + break; + } + } + } + + if (allValuesAreZero) { + // 如果所有初始化值都是零(或没有明确初始化但语法允许),使用 memset 优化 builder.createMemsetInst( - alloca, ConstantInteger::get(begin), - ConstantInteger::get(static_cast(counterNumbers[i])), - counterValues[i]); - begin += counterNumbers[i]; + alloca, // 目标数组的起始地址 + ConstantInteger::get(0), // 偏移量(通常为0),后续删除 + ConstantInteger::get(totalSizeInBytes), + ConstantInteger::get(0)); // 填充的总字节数 + } + else { + // **逐元素存储:遍历所有初始值,并为每个值生成一个 store 指令** + for (size_t k = 0; k < counterValues.size(); ++k) { + // 用于存储当前元素的索引列表 + std::vector currentIndices; + int tempLinearIndex = k; // 临时线性索引,用于计算多维索引 + + // **将线性索引转换为多维索引** + // 这个循环从最内层维度开始倒推,计算每个维度的索引 + // 假设是行主序(row-major order),这是 C/C++ 数组的标准存储方式 + for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) + { + // 计算当前维度的索引,并插入到列表的最前面 + currentIndices.insert(currentIndices.begin(), + ConstantInteger::get(static_cast(tempLinearIndex % dimSizes[dimIdx]))); + // 更新线性索引,用于计算下一个更高维度的索引 + tempLinearIndex /= dimSizes[dimIdx]; + } + + // **生成 store 指令,传入值、基指针和计算出的索引列表** + // 你的 builder.createStoreInst 签名需要能够接受这些参数 + // 假设你的 builder.createStoreInst(Value *val, Value *ptr, const std::vector &indices, ...) + builder.createStoreInst(counterValues[k], alloca, currentIndices); + } } } } + 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; + + // 使用 memset 将整个数组清零 + builder.createMemsetInst( + alloca, + ConstantInteger::get(0), + ConstantInteger::get(totalSizeInBytes), + ConstantInteger::get(0) + ); // 填充的总字节数 + } + // 标量变量如果没有初始化值,通常不生成额外的初始化指令,因为其内存已分配但未赋值。 + } + module->addVariable(name, alloca); } + return std::any(); }