[midend] GEP类型推断函数getIndexedType逻辑修复,增加数组type缓存池避免相同type ==操作返回假,修复实参形参类型转换判断逻辑,starttime stoptime提供支持(待后端测试)
This commit is contained in:
@@ -770,6 +770,7 @@ std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
|
||||
|
||||
if (allocatedType->isPointer()) {
|
||||
// 如果 AllocaInst 分配的是一个指针类型 (例如,用于存储函数参数的指针,如 int b[][20] 中的 b)
|
||||
// 即 `allocatedType` 是一个指向数组指针的指针 (e.g., [20 x i32]**)
|
||||
// 那么 GEP 的基指针是加载这个指针变量的值。
|
||||
gepBasePointer = builder.createLoadInst(alloc); // 加载出实际的指针值 (e.g., [20 x i32]*)
|
||||
// 对于这种参数指针,用户提供的索引直接作用于它。不需要额外的 0。
|
||||
@@ -777,6 +778,7 @@ std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
|
||||
} else {
|
||||
// 如果 AllocaInst 分配的是实际的数组数据 (例如,int b[10][20] 中的 b)
|
||||
// 那么 AllocaInst 本身就是 GEP 的基指针。
|
||||
// 这里的 `alloc` 是指向数组的指针 (e.g., [10 x [20 x i32]]*)
|
||||
gepBasePointer = alloc; // 类型是 [10 x [20 x i32]]*
|
||||
// 对于这种完整的数组分配,GEP 的第一个索引必须是 0,用于“步过”整个数组。
|
||||
gepIndices.push_back(ConstantInteger::get(0));
|
||||
@@ -856,32 +858,63 @@ std::any SysYIRGenerator::visitCall(SysYParser::CallContext *ctx) {
|
||||
|
||||
std::vector<Value *> args = {};
|
||||
if (funcName == "starttime" || funcName == "stoptime") {
|
||||
// 如果是starttime或stoptime函数
|
||||
// TODO: 这里需要处理starttime和stoptime函数的参数
|
||||
// args.emplace_back()
|
||||
args.emplace_back(
|
||||
ConstantInteger::get(static_cast<int>(ctx->getStart()->getLine())));
|
||||
} else {
|
||||
if (ctx->funcRParams() != nullptr) {
|
||||
args = std::any_cast<std::vector<Value *>>(visitFuncRParams(ctx->funcRParams()));
|
||||
}
|
||||
|
||||
auto params = function->getEntryBlock()->getArguments();
|
||||
// 获取形参列表。`getArguments()` 返回的是 `Argument*` 的集合,
|
||||
// 每个 `Argument` 代表一个函数形参,其 `getType()` 就是指向形参的类型的指针类型。
|
||||
auto formalParamsAlloca = function->getEntryBlock()->getArguments();
|
||||
|
||||
// 检查实参和形参数量是否匹配。
|
||||
if (args.size() != formalParamsAlloca.size()) {
|
||||
std::cerr << "Error: Function call argument count mismatch for function '" << funcName << "'." << std::endl;
|
||||
assert(false && "Function call argument count mismatch!");
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
// 参数类型转换
|
||||
if (params[i]->getType() != args[i]->getType() &&
|
||||
(params[i]->getNumDims() != 0 ||
|
||||
params[i]->getType()->as<PointerType>()->getBaseType() != args[i]->getType())) {
|
||||
ConstantValue * constValue = dynamic_cast<ConstantValue *>(args[i]);
|
||||
// 形参的类型 (e.g., i32, float, i32*, [10 x i32]*)
|
||||
Type* formalParamExpectedValueType = formalParamsAlloca[i]->getType()->as<PointerType>()->getBaseType();
|
||||
// 实参的实际类型 (e.g., i32, float, i32*, [67 x i32]*)
|
||||
Type* actualArgType = args[i]->getType();
|
||||
// 如果实参类型与形参类型不匹配,则尝试进行类型转换
|
||||
if (formalParamExpectedValueType != actualArgType) {
|
||||
ConstantValue *constValue = dynamic_cast<ConstantValue *>(args[i]);
|
||||
if (constValue != nullptr) {
|
||||
if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) {
|
||||
args[i] = ConstantInteger::get(static_cast<float>(constValue->getInt()));
|
||||
if (formalParamExpectedValueType->isInt() && actualArgType->isFloat()) {
|
||||
args[i] = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
|
||||
} else if (formalParamExpectedValueType->isFloat() && actualArgType->isInt()) {
|
||||
args[i] = ConstantFloating::get(static_cast<float>(constValue->getInt()));
|
||||
} else {
|
||||
args[i] = ConstantFloating::get(static_cast<int>(constValue->getFloat()));
|
||||
// 如果是常量但不是简单的 int/float 标量转换,
|
||||
// 或者是指针常量需要 bitcast,则让它进入非常量转换逻辑。
|
||||
// 例如,一个常量数组的地址,需要 bitcast 成另一种指针类型。
|
||||
// 目前不知道样例有没有这种情况,所以这里不做处理。
|
||||
}
|
||||
} else {
|
||||
if (params[i]->getType() == Type::getPointerType(Type::getFloatType())) {
|
||||
args[i] = builder.createIToFInst(args[i]);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// 1. 标量值类型转换 (例如:int_reg 到 float_reg,float_reg 到 int_reg)
|
||||
if (formalParamExpectedValueType->isInt() && actualArgType->isFloat()) {
|
||||
args[i] = builder.createFtoIInst(args[i]);
|
||||
} else if (formalParamExpectedValueType->isFloat() && actualArgType->isInt()) {
|
||||
args[i] = builder.createIToFInst(args[i]);
|
||||
}
|
||||
// 2. 指针类型转换 (例如数组退化:`[N x T]*` 到 `T*`,或兼容指针类型之间) TODO:不清楚有没有这种样例
|
||||
// 这种情况常见于数组参数,实参可能是一个更具体的数组指针类型,
|
||||
// 而形参是其退化后的基础指针类型。LLVM 的 `bitcast` 指令可以用于
|
||||
// 在相同大小的指针类型之间进行转换,这对于数组退化至关重要。
|
||||
// else if (formalParamType->isPointer() && actualArgType->isPointer()) {
|
||||
// 检查指针基类型是否兼容,或者是否是数组退化导致的类型不同。
|
||||
// 使用 bitcast,
|
||||
// args[i] = builder.createBitCastInst(args[i], formalParamType);
|
||||
// }
|
||||
// 3. 其他未预期的类型不匹配
|
||||
// 如果代码执行到这里,说明存在编译器前端未处理的类型不兼容或错误。
|
||||
else {
|
||||
// assert(false && "Unhandled type mismatch for function call argument.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user