diff --git a/src/mapleall/maple_be/src/be/lower.cpp b/src/mapleall/maple_be/src/be/lower.cpp index 6a00d972ceff5dff7194f84435861e25f46d566b..215b9012eb541d8a468b7937c94f797cccbd6c20 100644 --- a/src/mapleall/maple_be/src/be/lower.cpp +++ b/src/mapleall/maple_be/src/be/lower.cpp @@ -837,11 +837,10 @@ BlockNode *CGLowerer::LowerReturnStruct(NaryStmtNode &retNode) { MIRSymbol *retSt = curFunc->GetFormal(0); MIRPtrType *retTy = static_cast(retSt->GetType()); IassignNode *iassign = mirModule.CurFuncCodeMemPool()->New(); - if ((beCommon.GetTypeSize(retTy->GetPointedTyIdx().GetIdx()) > k16ByteSize) || (opnd0->GetPrimType() != PTY_agg)) { - iassign->SetTyIdx(retTy->GetTypeIndex()); - } else { + iassign->SetTyIdx(retTy->GetTypeIndex()); + if ((beCommon.GetTypeSize(retTy->GetPointedTyIdx().GetIdx()) <= k16ByteSize) && (opnd0->GetPrimType() == PTY_agg)) { /* struct goes into register. */ - iassign->SetTyIdx(retTy->GetPointedTyIdx()); + curFunc->SetStructReturnedInRegs(); } iassign->SetFieldID(0); iassign->SetRHS(opnd0); diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index f88b63df39106d179650d18949599e709c54319a..f99e698b1ad0fc872ecb91eb61726973c6d4b634 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -1925,16 +1925,15 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { Operand &lhsAddrOpnd = LoadIntoRegister(AddrOpnd, stmt.Opnd(0)->GetPrimType()); uint32 lhsOffset = 0; MIRType *stmtType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(stmt.GetTyIdx()); - MIRSymbol *addrSym = nullptr; - MIRPtrType *lhsPointerType = nullptr; - if (stmtType->GetPrimType() == PTY_agg) { - /* Move into regs */ - AddrofNode &addrofnode = static_cast(stmt.GetAddrExprBase()); - addrSym = mirModule.CurFunction()->GetLocalOrGlobalSymbol(addrofnode.GetStIdx()); - MIRType *addrty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(addrSym->GetTyIdx()); - lhsPointerType = static_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(addrty->GetTypeIndex())); - } else { - lhsPointerType = static_cast(stmtType); + MIRPtrType *lhsPointerType = static_cast(stmtType); + bool loadToRegs4StructReturn = false; + if (mirModule.CurFunction()->StructReturnedInRegs()) { + MIRSymbol *retSt = mirModule.CurFunction()->GetFormal(0); + if (stmt.Opnd(0)->GetOpCode() == OP_dread) { + DreadNode *dread = static_cast(stmt.Opnd(0)); + MIRSymbol *addrSym = mirModule.CurFunction()->GetLocalOrGlobalSymbol(dread->GetStIdx()); + loadToRegs4StructReturn = (retSt == addrSym); + } } MIRType *lhsType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(lhsPointerType->GetPointedTyIdx()); if (stmt.GetFieldID() != 0) { @@ -1979,18 +1978,12 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { rhsType = structType->GetFieldType(rhsDread->GetFieldID()); rhsOffset = static_cast(GetBecommon().GetFieldOffset(*structType, rhsDread->GetFieldID()).first); } - if (stmtType->GetPrimType() == PTY_agg) { + if (loadToRegs4StructReturn) { /* generate move to regs for agg return */ CHECK_FATAL(lhsSize <= k16ByteSize, "SelectAggIassign: illegal struct size"); AArch64CallConvImpl parmlocator(GetBecommon()); CCLocInfo pLoc; - MIRSymbol *retSt = GetBecommon().GetMIRModule().CurFunction()->GetFormal(0); - if (retSt == addrSym) { - /* return value */ - parmlocator.LocateNextParm(*lhsType, pLoc, true, GetBecommon().GetMIRModule().CurFunction()); - } else { - parmlocator.InitCCLocInfo(pLoc); - } + parmlocator.LocateNextParm(*lhsType, pLoc, true, GetBecommon().GetMIRModule().CurFunction()); /* aggregates are 8 byte aligned. */ Operand *rhsmemopnd = nullptr; RegOperand *result[kFourRegister]; /* up to 2 int or 4 fp */ @@ -2187,7 +2180,7 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { rhsOffset = static_cast(GetBecommon().GetFieldOffset(*rhsStructType, rhsIread->GetFieldID()).first); isRefField = GetBecommon().IsRefField(*rhsStructType, rhsIread->GetFieldID()); } - if (stmtType->GetPrimType() == PTY_agg) { + if (loadToRegs4StructReturn) { /* generate move to regs. */ CHECK_FATAL(lhsSize <= k16ByteSize, "SelectAggIassign: illegal struct size"); RegOperand *result[kTwoRegister]; /* maximum 16 bytes, 2 registers */ diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 4080108d25a14ec54b87b51ae354265868e52016..4df1567b1067521a079595279947af77125dbf3f 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -416,6 +416,9 @@ class MIRFunction { void SetHasAsm(); bool HasAsm() const; + void SetStructReturnedInRegs(); + bool StructReturnedInRegs() const; + void SetReturnStruct(const MIRType *retType); bool IsEmpty() const; diff --git a/src/mapleall/maple_ir/src/mir_function.cpp b/src/mapleall/maple_ir/src/mir_function.cpp index 75cafccb6b8d978e80c49182cb822073760316f3..7c6c48f059f6f4b9be1e2e0399a4dcc87da17042 100644 --- a/src/mapleall/maple_ir/src/mir_function.cpp +++ b/src/mapleall/maple_ir/src/mir_function.cpp @@ -32,6 +32,7 @@ enum FuncProp : uint32_t { kFuncPropNeverReturn = 1U << 4, // the function when called never returns kFuncPropHasSetjmp = 1U << 5, // the function contains call to setjmp kFuncPropHasAsm = 1U << 6, // the function has use of inline asm + kFuncPropStructReturnedInRegs = 1U << 7, // the function returns struct in registers }; } // namespace @@ -207,6 +208,14 @@ bool MIRFunction::HasAsm() const { return ((flag & kFuncPropHasAsm) != kTypeflagZero); } +void MIRFunction::SetStructReturnedInRegs() { + flag |= kFuncPropStructReturnedInRegs; +} + +bool MIRFunction::StructReturnedInRegs() const { + return ((flag & kFuncPropStructReturnedInRegs) != kTypeflagZero); +} + void MIRFunction::SetAttrsFromSe(uint8 specialEffect) { // NoPrivateDefEffect if ((specialEffect & kDefEffect) == kDefEffect) {