@@ -1,5 +1,6 @@
# include "Reg2Mem.h"
# include "SysYIROptUtils.h" // 如果有的话
# include "SysYIROptUtils.h"
# include "SysYIRPrinter.h"
extern int DEBUG ; // 全局调试标志
@@ -33,15 +34,15 @@ void Reg2MemContext::run(Function *func) {
bool Reg2MemContext : : isPromotableToMemory ( Value * val ) {
// 参数和指令结果是 SSA 值
if ( DEBUG ) {
if ( val - > getName ( ) = = " " ) {
assert( false & & " Value name should not be empty in Reg2MemContext::isPromotableToMemory" ) ;
}
std : : cout < < " Checking if value is promotable to memory: " < < val - > getName ( ) < < std : : endl ;
// if(val->getName() == ""){
// assert(false && " Value name should not be empty in Reg2MemContext::isPromotableToMemory");
// }
// std::cout << " Checking if value is promotable to memory: " << val->getName() << std::endl;
}
if ( dynamic_cast < Argument * > ( val ) | | dynamic_cast < Instruction * > ( val ) ) {
// 如果值已经是指针类型,则通常不为其分配额外的内存,因为它已经是一个地址。
// (除非我们想将其值也存储起来,这通常不用于 Reg2Mem)
// Reg2Mem 关注的是将非指针值从寄存器语义转换为内存语义。
// // Reg2Mem 关注的是将非指针值从寄存器语义转换为内存语义。
if ( val - > getType ( ) - > isPointer ( ) ) {
return false ;
}
@@ -60,9 +61,10 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// 1. 为函数参数分配内存
builder - > setPosition ( entryBlock , entryBlock - > begin ( ) ) ; // 确保在入口块的开始位置插入
for ( auto arg : func - > getArguments ( ) ) {
if ( isPromotableToMemory ( arg ) ) {
// 默认情况下,将所有参数是提升到内存
// if (isPromotableToMemory(arg)) {
// 参数的类型就是 AllocaInst 需要分配的类型
AllocaInst * alloca = builder - > createAllocaInst ( arg - > getType ( ) , { } ) ;
AllocaInst * alloca = builder - > createAllocaInst ( Type : : getPointerType ( arg- > getType ( ) ) , { } , arg - > getName ( ) + " .reg2mem " );
// 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步)
builder - > createStoreInst ( arg , alloca ) ;
valueToAllocaMap [ arg ] = alloca ;
@@ -71,17 +73,19 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// 通常 alloca 都在 entry block 的最开始
// 这里我们只是创建,并让 builder 决定插入位置 (通常在当前插入点)
// 如果需要严格控制顺序,可能需要手动 insert 到 instruction list
}
// }
}
// 2. 为指令结果分配内存
// 遍历所有基本块和指令,找出所有需要分配 Alloca 的指令结果
for ( auto & bb : func - > getBasicBlocks ( ) ) {
for ( auto & inst : bb - > getInstructions_Range ( ) ) {
// SysYPrinter::printInst(inst.get());
// 只有有结果的指令才可能需要分配内存
// (例如 BinaryInst, CallInst, LoadInst, PhiInst 等)
// StoreInst, BranchInst, ReturnInst 等没有结果的指令不需要
if ( inst . get ( ) - > getType ( ) - > isVoid ( ) ) { // 没有返回值的指令
if ( dynamic_cast < AllocaInst * > ( inst . get ( ) ) | | inst . get ( ) - > getType ( ) - > isVoid ( ) ) {
continue ;
}
@@ -90,7 +94,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// AllocaInst 应该在入口块,而不是当前指令所在块
// 这里我们只是创建,并稍后调整其位置
// 通常的做法是在循环结束后统一将 alloca 放到 entryBlock 的顶部
AllocaInst * alloca = builder - > createAllocaInst ( inst . get ( ) - > getType ( ) , { } ) ;
AllocaInst * alloca = builder - > createAllocaInst ( Type : : getPointerType ( inst. get ( ) - > getType ( ) ) , { } , inst . get ( ) - > getName ( ) + " .reg2mem " );
valueToAllocaMap [ inst . get ( ) ] = alloca ;
}
}