diff --git a/src/mapleall/maple_be/include/be/lower.h b/src/mapleall/maple_be/include/be/lower.h index d4c3a7c82417d8beebc19de6e6555ab49f5c3e01..31694966eded1268a51061039a066037ea66e5b4 100644 --- a/src/mapleall/maple_be/include/be/lower.h +++ b/src/mapleall/maple_be/include/be/lower.h @@ -153,7 +153,7 @@ class CGLowerer { bool isIntrinAssign = false); BlockNode *LowerIntrinsiccallAassignedToAssignStmt(IntrinsiccallNode &intrinsicCall); BlockNode *LowerCallAssignedStmt(StmtNode &stmt, bool uselvar = false); - bool LowerStructReturn(BlockNode &blk, StmtNode *stmt, StmtNode *nextStmt, bool &lvar); + bool LowerStructReturn(BlockNode &blk, StmtNode *stmt, StmtNode *&nextStmt, bool &lvar, BlockNode *oldblk); BlockNode *LowerMemop(StmtNode&); BaseNode *LowerRem(BaseNode &rem, BlockNode &block); @@ -231,6 +231,7 @@ class CGLowerer { int64 seed = 0; SimplifyMemOp simplifyMemOp; static const std::string kIntrnRetValPrefix; + static const std::string kUserRetValPrefix; static constexpr PUIdx kFuncNotFound = PUIdx(-1); static constexpr int kThreeDimArray = 3; diff --git a/src/mapleall/maple_be/src/be/lower.cpp b/src/mapleall/maple_be/src/be/lower.cpp index 92a4bc08e22551d5a1af6b9e06a1d1f56dad519d..e7497eb59335eb6c03fe1caee2ec7837dbc28174 100644 --- a/src/mapleall/maple_be/src/be/lower.cpp +++ b/src/mapleall/maple_be/src/be/lower.cpp @@ -79,6 +79,7 @@ std::vector> extFuncs; } const std::string CGLowerer::kIntrnRetValPrefix = "__iret"; +const std::string CGLowerer::kUserRetValPrefix = "__uret"; MIRSymbol *CGLowerer::CreateNewRetVar(const MIRType &ty, const std::string &prefix) { const uint32 bufSize = 257; @@ -1407,10 +1408,36 @@ static PrimType IsStructElementSame(MIRType *ty) { } #endif -bool CGLowerer::LowerStructReturn(BlockNode &newBlk, StmtNode *stmt, StmtNode *nextStmt, bool &lvar) { - if (!nextStmt || nextStmt->op != OP_dassign) { +// return true if successfully lowered; nextStmt is in/out +bool CGLowerer::LowerStructReturn(BlockNode &newBlk, StmtNode *stmt, StmtNode *&nextStmt, bool &lvar, BlockNode *oldBlk) { + if (!nextStmt) { return false; } + CallReturnVector *p2nrets = stmt->GetCallReturnVector(); + if (p2nrets->size() == 0) { + return false; + } + CallReturnPair retPair = (*p2nrets)[0]; + if (retPair.second.IsReg()) { + return false; + } + MIRSymbol *retSym = mirModule.CurFunction()->GetLocalOrGlobalSymbol(retPair.first); + if (retSym->GetType()->GetPrimType() != PTY_agg) { + return false; + } + if (nextStmt->op != OP_dassign) { + // introduce a temporary and insert a dassign whose rhs is this temporary + // and whose lhs is retSym + MIRSymbol *temp = CreateNewRetVar(*retSym->GetType(), kUserRetValPrefix); + BaseNode *rhs = mirModule.GetMIRBuilder()->CreateExprDread(*temp->GetType(), 0, *temp); + DassignNode *dass = mirModule.GetMIRBuilder()->CreateStmtDassign(retPair.first, retPair.second.GetFieldID(), rhs); + oldBlk->InsertBefore(nextStmt, dass); + nextStmt = dass; + // update CallReturnVector to the new temporary + (*p2nrets)[0].first = temp->GetStIdx(); + (*p2nrets)[0].second.SetFieldID(0); + } + // now, it is certain that nextStmt is a dassign BaseNode *bnode = static_cast(nextStmt)->GetRHS(); if (bnode->GetOpCode() != OP_dread) { return false; @@ -1426,17 +1453,6 @@ bool CGLowerer::LowerStructReturn(BlockNode &newBlk, StmtNode *stmt, StmtNode *n if (dnode->GetPrimType() != PTY_agg) { return false; } - CallReturnVector *p2nrets = nullptr; - if (stmt->GetOpCode() == OP_callassigned) { - auto *callNode = static_cast(stmt); - p2nrets = &callNode->GetReturnVec(); - } else if (stmt->GetOpCode() == OP_icallassigned) { - auto *icallNode = static_cast(stmt); - p2nrets = &icallNode->GetReturnVec(); - } - if (!p2nrets || p2nrets->size() != 1) { - return false; - } CallReturnPair pair = (*p2nrets)[0]; if (pair.first != dnode->GetStIdx() || pair.second.GetFieldID() != dnode->GetFieldID()) { return false; @@ -1760,7 +1776,7 @@ BlockNode *CGLowerer::LowerBlock(BlockNode &block) { case OP_icallassigned: { // pass the addr of lvar if this is a struct call assignment bool lvar = false; - if (LowerStructReturn(*newBlk, stmt, nextStmt, lvar)) { + if (LowerStructReturn(*newBlk, stmt, nextStmt, lvar, &block)) { nextStmt = nextStmt->GetNext(); // skip dassign } else { newBlk->AppendStatementsFromBlock(*LowerCallAssignedStmt(*stmt, lvar)); diff --git a/src/mapleall/maple_me/include/lmbc_memlayout.h b/src/mapleall/maple_me/include/lmbc_memlayout.h index 59da3e5b0bde3a03a8c07fb0873530eb057a0656..7cea863a221a68fc670c5c458264bc53394a62ff 100644 --- a/src/mapleall/maple_me/include/lmbc_memlayout.h +++ b/src/mapleall/maple_me/include/lmbc_memlayout.h @@ -71,7 +71,7 @@ class LMBCMemLayout { seg_upformal(MS_upformal), seg_formal(MS_formal), seg_actual(MS_actual), - seg_FPbased(MS_FPbased, -GetPrimTypeSize(PTY_ptr)), + seg_FPbased(MS_FPbased), seg_SPbased(MS_SPbased), sym_alloc_table(mallocator->Adapter()) { sym_alloc_table.resize(f->GetSymTab()->GetSymbolTableSize());