From ab1725b62f3331751e6798f4ecd8936b0b159a93 Mon Sep 17 00:00:00 2001 From: William Chen Date: Wed, 27 Apr 2022 08:21:26 -0700 Subject: [PATCH 1/4] Initial pass for comsuming lmbc in cg. --- .../maple_be/include/be/common_utils.h | 1 + .../include/cg/aarch64/aarch64_call_conv.h | 3 + .../include/cg/aarch64/aarch64_cgfunc.h | 76 ++- .../include/cg/aarch64/aarch64_phases.def | 40 +- src/mapleall/maple_be/include/cg/cgfunc.h | 114 ++++- src/mapleall/maple_be/include/cg/memlayout.h | 2 +- .../maple_be/src/cg/aarch64/aarch64_args.cpp | 3 + .../src/cg/aarch64/aarch64_call_conv.cpp | 23 + .../src/cg/aarch64/aarch64_cgfunc.cpp | 443 +++++++++++++++++- .../src/cg/aarch64/aarch64_memlayout.cpp | 15 + .../src/cg/aarch64/aarch64_offset_adjust.cpp | 5 + .../src/cg/aarch64/aarch64_proepilog.cpp | 31 +- .../maple_be/src/cg/cg_phasemanager.cpp | 4 +- src/mapleall/maple_be/src/cg/cgfunc.cpp | 127 +++++ 14 files changed, 834 insertions(+), 53 deletions(-) diff --git a/src/mapleall/maple_be/include/be/common_utils.h b/src/mapleall/maple_be/include/be/common_utils.h index 7009aa9651..205cbf8161 100644 --- a/src/mapleall/maple_be/include/be/common_utils.h +++ b/src/mapleall/maple_be/include/be/common_utils.h @@ -65,6 +65,7 @@ constexpr uint32 k12ByteSize = 12; constexpr uint32 k14ByteSize = 14; constexpr uint32 k15ByteSize = 15; constexpr uint32 k16ByteSize = 16; +constexpr uint32 k32ByteSize = 32; constexpr uint32 k1EightBytesSize = 8; constexpr uint32 k2EightBytesSize = 16; diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_call_conv.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_call_conv.h index fe5322398e..e66975ca21 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_call_conv.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_call_conv.h @@ -42,6 +42,9 @@ class AArch64CallConvImpl { void InitCCLocInfo(CCLocInfo &pLoc) const; + /* for lmbc */ + uint32 FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize); + /* return value related */ void InitReturnInfo(MIRType &retTy, CCLocInfo &pLoc); diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h index 947a78306d..a4bc2e6221 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -27,6 +27,19 @@ #include "aarch64_call_conv.h" namespace maplebe { +class LmbcArgInfo { + public: + LmbcArgInfo(MapleAllocator &mallocator) + : lmbcCallArgs(mallocator.Adapter()), + lmbcCallArgTypes(mallocator.Adapter()), + lmbcCallArgOffsets(mallocator.Adapter()), + lmbcCallArgNumOfRegs(mallocator.Adapter()) {} + MapleVector lmbcCallArgs; + MapleVector lmbcCallArgTypes; + MapleVector lmbcCallArgOffsets; + MapleVector lmbcCallArgNumOfRegs; // # of regs needed to complete struct +}; + class AArch64CGFunc : public CGFunc { public: AArch64CGFunc(MIRModule &mod, CG &c, MIRFunction &f, BECommon &b, @@ -51,7 +64,7 @@ class AArch64CGFunc : public CGFunc { if (f.GetAttr(FUNCATTR_varargs) || f.HasVlaOrAlloca()) { SetHasVLAOrAlloca(true); } - SetUseFP(CGOptions::UseFramePointer() || HasVLAOrAlloca() || !f.GetModule()->IsCModule()); + SetUseFP(CGOptions::UseFramePointer() || HasVLAOrAlloca() || !f.GetModule()->IsCModule() || f.GetModule()->GetFlavor() == MIRFlavor::kFlavorLmbc); } ~AArch64CGFunc() override = default; @@ -86,6 +99,7 @@ class AArch64CGFunc : public CGFunc { return kRFLAG; } + MIRType *GetAggTyFromCallSite(StmtNode *stmt); RegOperand &GetOrCreateResOperand(const BaseNode &parent, PrimType primType); void IntrinsifyGetAndAddInt(ListOperand &srcOpnds, PrimType pty); @@ -109,9 +123,13 @@ class AArch64CGFunc : public CGFunc { bool needLow12 = false); MemOperand *FixLargeMemOpnd(MemOperand &memOpnd, uint32 align); MemOperand *FixLargeMemOpnd(MOperator mOp, MemOperand &memOpnd, uint32 dSize, uint32 opndIdx); + void LmbcSelectParmList(ListOperand *srcOpnds); void SelectAggDassign(DassignNode &stmt) override; void SelectIassign(IassignNode &stmt) override; void SelectIassignoff(IassignoffNode &stmt) override; + void SelectIassignfpoff(IassignFPoffNode &stmt, Operand &opnd) override; + void SelectIassignspoff(PrimType pTy, int32 offset, Operand &opnd) override; + void SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) override; void SelectAggIassign(IassignNode &stmt, Operand &lhsAddrOpnd) override; void SelectReturn(Operand *opnd0) override; void SelectIgoto(Operand *opnd0) override; @@ -156,7 +174,8 @@ class AArch64CGFunc : public CGFunc { void SelectAddrof(Operand &result, StImmOperand &stImm, FieldID field = 0); void SelectAddrof(Operand &result, MemOperand &memOpnd, FieldID field = 0); Operand *SelectCSyncCmpSwap(const IntrinsicopNode &intrinopNode, PrimType pty, bool retBool = false); - Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent) override; + Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent, bool isAddrofoff = false) override; + Operand *SelectAddrofoff(AddrofoffNode &expr, const BaseNode &parent) override; Operand &SelectAddrofFunc(AddroffuncNode &expr, const BaseNode &parent) override; Operand &SelectAddrofLabel(AddroflabelNode &expr, const BaseNode &parent) override; @@ -165,6 +184,7 @@ class AArch64CGFunc : public CGFunc { Operand *SelectIread(const BaseNode &parent, IreadNode &expr, int extraOffset = 0, PrimType finalBitFieldDestType = kPtyInvalid) override; Operand *SelectIreadoff(const BaseNode &parent, IreadoffNode &ireadoff) override; + Operand *SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) override; Operand *SelectIntConst(MIRIntConst &intConst) override; Operand *HandleFmovImm(PrimType stype, int64 val, MIRConst &mirConst, const BaseNode &parent); Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) override; @@ -273,7 +293,7 @@ class AArch64CGFunc : public CGFunc { RegOperand &CreateRegisterOperandOfType(PrimType primType); RegOperand &CreateRegisterOperandOfType(RegType regType, uint32 byteLen); RegOperand &CreateRflagOperand(); - RegOperand &GetOrCreateSpecialRegisterOperand(PregIdx sregIdx, PrimType primType = PTY_i64); + RegOperand &GetOrCreateSpecialRegisterOperand(PregIdx sregIdx, PrimType primType); MemOperand *GetOrCreatSpillMem(regno_t vrNum); void FreeSpillRegMem(regno_t vrNum); RegOperand &GetOrCreatePhysicalRegisterOperand(AArch64reg regNO, uint32 size, RegType type, uint32 flag = 0); @@ -388,7 +408,13 @@ class AArch64CGFunc : public CGFunc { } RegOperand &GetOrCreateStackBaseRegOperand() override { - return GetOrCreatePhysicalRegisterOperand(RFP, kSizeOfPtr * kBitsPerByte, kRegTyInt); + AArch64reg reg; + if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + reg = RSP; + } else { + reg = RFP; + } + return GetOrCreatePhysicalRegisterOperand(reg, kSizeOfPtr * kBitsPerByte, kRegTyInt); } RegOperand &GenStructParamIndex(RegOperand &base, const BaseNode &indexExpr, int shift, PrimType baseType, @@ -453,6 +479,9 @@ class AArch64CGFunc : public CGFunc { void GenerateCleanupCode(BB &bb) override; bool NeedCleanup() override; void GenerateCleanupCodeForExtEpilog(BB &bb) override; + uint32 FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) override; + void AssignLmbcFormalParams() override; + RegOperand *GenLmbcParamLoad(int32 offset, uint32 byteSize, RegType regType, PrimType primType); Operand *GetBaseReg(const AArch64SymbolAlloc &symAlloc); int32 GetBaseOffset(const SymbolAlloc &symAlloc) override; @@ -654,6 +683,44 @@ class AArch64CGFunc : public CGFunc { return alignPow; } + LmbcArgInfo *GetLmbcArgInfo() { + return lmbcArgInfo; + } + + void SetLmbcArgInfo(LmbcArgInfo *p) { + lmbcArgInfo = p; + } + + void SetLmbcArgInfo(RegOperand *reg, PrimType pTy, int32 ofst, int32 regs) { + GetLmbcCallArgs().emplace_back(reg); + GetLmbcCallArgTypes().emplace_back(pTy); + GetLmbcCallArgOffsets().emplace_back(ofst); + GetLmbcCallArgNumOfRegs().emplace_back(regs); + } + + void ResetLmbcArgInfo() { + GetLmbcCallArgs().clear(); + GetLmbcCallArgTypes().clear(); + GetLmbcCallArgOffsets().clear(); + GetLmbcCallArgNumOfRegs().clear(); + } + + MapleVector &GetLmbcCallArgs() { + return lmbcArgInfo->lmbcCallArgs; + } + + MapleVector &GetLmbcCallArgTypes() { + return lmbcArgInfo->lmbcCallArgTypes; + } + + MapleVector &GetLmbcCallArgOffsets() { + return lmbcArgInfo->lmbcCallArgOffsets; + } + + MapleVector &GetLmbcCallArgNumOfRegs() { + return lmbcArgInfo->lmbcCallArgNumOfRegs; + } + private: enum RelationOperator : uint8 { kAND, @@ -720,6 +787,7 @@ class AArch64CGFunc : public CGFunc { int32 splitStpldpBaseOffset = 0; regno_t methodHandleVreg = -1; uint32 alignPow = 5; /* function align pow defaults to 5 i.e. 2^5*/ + LmbcArgInfo *lmbcArgInfo = nullptr; void SelectLoadAcquire(Operand &dest, PrimType dtype, Operand &src, PrimType stype, AArch64isa::MemoryOrdering memOrd, bool isDirect); diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def b/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def index 1b72c5cd25..82c0c172cb 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def @@ -18,14 +18,16 @@ ADDTARGETPHASE("handlefunction", true); ADDTARGETPHASE("moveargs", true); /* SSA PHASES */ - ADDTARGETPHASE("cgssaconstruct", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgcopyprop", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgpeephole", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgtargetprop", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgdeadcodeelimination", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgsplitcriticaledge", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgphielimination", CGOptions::DoCGSSA()); - ADDTARGETPHASE("cgregcoalesce", CGOptions::DoCGSSA()); + if (GetMIRModule()->GetFlavor() != MIRFlavor::kFlavorLmbc) { + ADDTARGETPHASE("cgssaconstruct", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgcopyprop", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgpeephole", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgtargetprop", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgdeadcodeelimination", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgsplitcriticaledge", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgphielimination", CGOptions::DoCGSSA()); + ADDTARGETPHASE("cgregcoalesce", CGOptions::DoCGSSA()); + } /* Normal OPT PHASES */ ADDTARGETPHASE("cgprepeephole", CGOptions::DoPrePeephole()); ADDTARGETPHASE("ebo", CGOptions::DoEBO()); @@ -33,20 +35,24 @@ ADDTARGETPHASE("ico", CGOptions::DoICO()) ADDTARGETPHASE("cfgo", !GetMIRModule()->IsCModule() && CGOptions::DoCFGO()); - ADDTARGETPHASE("storeloadopt", CGOptions::DoStoreLoadOpt() && !CGOptions::DoCGSSA()) - ADDTARGETPHASE("globalopt", CGOptions::DoGlobalOpt()) - ADDTARGETPHASE("clearrdinfo", (CGOptions::DoStoreLoadOpt()) || CGOptions::DoGlobalOpt()) + if (GetMIRModule()->GetFlavor() != MIRFlavor::kFlavorLmbc) { + ADDTARGETPHASE("storeloadopt", CGOptions::DoStoreLoadOpt() && !CGOptions::DoCGSSA()); + ADDTARGETPHASE("globalopt", CGOptions::DoGlobalOpt()); + } + ADDTARGETPHASE("clearrdinfo", (CGOptions::DoStoreLoadOpt()) || CGOptions::DoGlobalOpt()); - ADDTARGETPHASE("prepeephole1", CGOptions::DoPrePeephole()) + ADDTARGETPHASE("prepeephole1", CGOptions::DoPrePeephole()); ADDTARGETPHASE("ebo1", CGOptions::DoEBO()); ADDTARGETPHASE("prescheduling", !GetMIRModule()->IsJavaModule() && CGOptions::DoPreSchedule()); ADDTARGETPHASE("raopt", CGOptions::DoPreLSRAOpt()); ADDTARGETPHASE("cgsplitcriticaledge", GetMIRModule()->IsCModule()); ADDTARGETPHASE("regalloc", true); - ADDTARGETPHASE("regsaves", GetMIRModule()->IsCModule() && CGOptions::DoRegSavesOpt()) - ADDTARGETPHASE("storeloadopt", GetMIRModule()->IsCModule() && CGOptions::DoStoreLoadOpt()) - ADDTARGETPHASE("globalopt", CGOptions::DoCGSSA()); - ADDTARGETPHASE("clearrdinfo", GetMIRModule()->IsCModule() && (CGOptions::DoStoreLoadOpt() || CGOptions::DoGlobalOpt())) + ADDTARGETPHASE("regsaves", GetMIRModule()->IsCModule() && CGOptions::DoRegSavesOpt()); + if (GetMIRModule()->GetFlavor() != MIRFlavor::kFlavorLmbc) { + ADDTARGETPHASE("storeloadopt", GetMIRModule()->IsCModule() && CGOptions::DoStoreLoadOpt()); + ADDTARGETPHASE("globalopt", CGOptions::DoCGSSA()); + } + ADDTARGETPHASE("clearrdinfo", GetMIRModule()->IsCModule() && (CGOptions::DoStoreLoadOpt() || CGOptions::DoGlobalOpt())); ADDTARGETPHASE("generateproepilog", true); ADDTARGETPHASE("framefinalize", true); ADDTARGETPHASE("dbgfixcallframeoffsets", true); @@ -61,4 +67,4 @@ ADDTARGETPHASE("scheduling", CGOptions::DoSchedule()); ADDTARGETPHASE("alignanalysis", GetMIRModule()->IsCModule() && CGOptions::DoAlignAnalysis()); ADDTARGETPHASE("fixshortbranch", true); - ADDTARGETPHASE("cgemit", true); \ No newline at end of file + ADDTARGETPHASE("cgemit", true); diff --git a/src/mapleall/maple_be/include/cg/cgfunc.h b/src/mapleall/maple_be/include/cg/cgfunc.h index d803860193..2afd1560dd 100644 --- a/src/mapleall/maple_be/include/cg/cgfunc.h +++ b/src/mapleall/maple_be/include/cg/cgfunc.h @@ -76,6 +76,72 @@ class SpillMemOperandSet { MapleSet reuseSpillLocMem; }; +class LmbcFormalParamInfo { + public: + explicit LmbcFormalParamInfo(PrimType pType, uint32 ofst, uint32 sz) : + primType(pType), offset(ofst), size(sz), regNO(0), vregNO(0), numRegs(0), fpSize(0), isPureFloat(false) {} + + virtual ~LmbcFormalParamInfo() = default; + + PrimType GetPrimType() { + return primType; + } + void SetPrimType(PrimType pType) { + primType = pType; + } + uint32 GetOffset() { + return offset; + } + void SetOffset(uint32 ofs) { + offset = ofs; + } + uint32 GetSize() { + return size; + } + void SetSize(uint32 sz) { + size = sz; + } + regno_t GetRegNO() { + return regNO; + } + void SetRegNO(regno_t reg) { + regNO = reg; + } + regno_t GetVregNO() { + return vregNO; + } + void SetVregNO(regno_t reg) { + vregNO = reg; + } + uint32 GetNumRegs() { + return numRegs; + } + void SetNumRegs(uint32 num) { + numRegs = num; + } + uint32 GetFpSize() { + return fpSize; + } + void SetFpSize(uint32 sz) { + fpSize = sz; + } + bool IsPureFloat() { + return isPureFloat; + } + void SetIsPureFloat() { + isPureFloat = true; + } + private: + PrimType primType; + uint32 offset; + uint32 size; /* size primtype or struct */ + regno_t regNO; /* param reg num or starting reg num if numRegs > 0 */ + regno_t vregNO; /* if no explicit regassing from IR, create move from param reg */ + uint32 numRegs; /* number of regs for struct param */ + uint32 fpSize; /* size of fp param if isPureFloat */ + bool isPureFloat; +}; + #if TARGARM32 class LiveRange; #endif /* TARGARM32 */ @@ -147,6 +213,10 @@ class CGFunc { virtual bool NeedCleanup() = 0; virtual void GenerateCleanupCodeForExtEpilog(BB &bb) = 0; + void CreateLmbcFormalParamInfo(); + virtual uint32 FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) = 0; + virtual void AssignLmbcFormalParams() = 0; + LmbcFormalParamInfo *GetLmbcFormalParamInfo(uint32 offset); void GenerateLoc(StmtNode *stmt, unsigned &lastSrcLoc, unsigned &lastMplLoc); int32 GetFreqFromStmt(uint32 stmtId); void GenerateInstruction(); @@ -184,6 +254,9 @@ class CGFunc { virtual void SelectAggDassign(DassignNode &stmt) = 0; virtual void SelectIassign(IassignNode &stmt) = 0; virtual void SelectIassignoff(IassignoffNode &stmt) = 0; + virtual void SelectIassignfpoff(IassignFPoffNode &stmt, Operand &opnd) = 0; + virtual void SelectIassignspoff(PrimType pTy, int32 offset, Operand &opnd) = 0; + virtual void SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) = 0; virtual void SelectAggIassign(IassignNode &stmt, Operand &lhsAddrOpnd) = 0; virtual void SelectReturn(Operand *opnd) = 0; virtual void SelectIgoto(Operand *opnd0) = 0; @@ -221,12 +294,14 @@ class CGFunc { /* select expr */ virtual Operand *SelectDread(const BaseNode &parent, AddrofNode &expr) = 0; virtual RegOperand *SelectRegread(RegreadNode &expr) = 0; - virtual Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent) = 0; + virtual Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent, bool isAddrofoff = false) = 0; + virtual Operand *SelectAddrofoff(AddrofoffNode &expr, const BaseNode &parent) = 0; virtual Operand &SelectAddrofFunc(AddroffuncNode &expr, const BaseNode &parent) = 0; virtual Operand &SelectAddrofLabel(AddroflabelNode &expr, const BaseNode &parent) = 0; virtual Operand *SelectIread(const BaseNode &parent, IreadNode &expr, int extraOffset = 0, PrimType finalBitFieldDestType = kPtyInvalid) = 0; virtual Operand *SelectIreadoff(const BaseNode &parent, IreadoffNode &ireadoff) = 0; + virtual Operand *SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) = 0; virtual Operand *SelectIntConst(MIRIntConst &intConst) = 0; virtual Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) = 0; virtual Operand *SelectDoubleConst(MIRDoubleConst &doubleConst, const BaseNode &parent) = 0; @@ -868,6 +943,39 @@ class CGFunc { loops.emplace_back(&loop); } + MapleVector &GetLmbcParamVec() { + return lmbcParamVec; + } + + void IncLmbcArgsInRegs(RegType ty) { + if (ty == kRegTyInt) { + lmbcIntArgs++; + } else { + lmbcFpArgs++; + } + } + + int16 GetLmbcArgsInRegs(RegType ty) { + return ty == kRegTyInt ? lmbcIntArgs : lmbcFpArgs; + } + + void ResetLmbcArgsInRegs() { + lmbcIntArgs = 0; + lmbcFpArgs = 0; + } + + void IncLmbcTotalArgs() { + lmbcTotalArgs++; + } + + int16 GetLmbcTotalArgs() { + return lmbcTotalArgs; + } + + void ResetLmbcTotalArgs() { + lmbcTotalArgs = 0; + } + MapleVector &GetAllBBs() { return bbVec; } @@ -1205,6 +1313,10 @@ class CGFunc { MapleVector lrVec; #endif /* TARGARM32 */ MapleVector loops; + MapleVector lmbcParamVec; + int32 lmbcIntArgs = 0; + int32 lmbcFpArgs = 0; + int32 lmbcTotalArgs = 0; CGCFG *theCFG = nullptr; uint32 nextSpillLocation = 0; diff --git a/src/mapleall/maple_be/include/cg/memlayout.h b/src/mapleall/maple_be/include/cg/memlayout.h index 1f9b50ea21..6e27c0e7e2 100644 --- a/src/mapleall/maple_be/include/cg/memlayout.h +++ b/src/mapleall/maple_be/include/cg/memlayout.h @@ -221,7 +221,7 @@ class MemLayout { return segArgsRegPassed; } - const MemSegment &GetSegArgsStkPass() const { + const MemSegment &GetSegArgsToStkPass() const { return segArgsToStkPass; } diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp index 46e0ae1922..9e1dd18d7e 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp @@ -20,6 +20,9 @@ namespace maplebe { using namespace maple; void AArch64MoveRegArgs::Run() { + if (cgFunc->GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + return; + } MoveVRegisterArgs(); MoveRegisterArgs(); } diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_call_conv.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_call_conv.cpp index 8201883bd3..511302deba 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_call_conv.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_call_conv.cpp @@ -141,6 +141,7 @@ uint32 ProcessStructWhenClassifyAggregate(const BECommon &be, MIRStructType &str } } if (isF32 || isF64) { + CHECK_FATAL(numRegs <=classesLength, "ClassifyAggregate: num regs exceed limit"); for (uint32 i = 0; i < numRegs; ++i) { classes[i] = kAArch64FloatClass; } @@ -204,6 +205,28 @@ int32 ClassifyAggregate(const BECommon &be, MIRType &mirType, AArch64ArgumentCla } } +/* external interface to look for pure float struct */ +uint32 AArch64CallConvImpl::FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) { + if (structType.GetSize() > k32ByteSize) { + return 0; + } + AArch64ArgumentClass classes[kMaxRegCount]; + uint32 numRegs = ProcessStructWhenClassifyAggregate(beCommon, structType, classes, kMaxRegCount, fpSize); + if (numRegs) { + bool isPure = true; + for (uint i = 0; i < numRegs; ++i) { + if (classes[i] != kAArch64FloatClass) { + isPure = false; + break; + } + } + if (isPure) { + return numRegs; + } + } + return 0; +} + void AArch64CallConvImpl::InitCCLocInfo(CCLocInfo &pLoc) const { pLoc.reg0 = kRinvalid; pLoc.reg1 = kRinvalid; 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 5b2c49a50d..c18dc74019 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -149,6 +149,19 @@ MOperator PickLdStInsn(bool isLoad, uint32 bitSize, PrimType primType, AArch64is } } +bool IsBlkassignForPush(BlkassignoffNode &bNode) +{ + BaseNode *dest = bNode.Opnd(0); + bool spBased = false; + if (dest->GetOpCode() == OP_regread) { + RegreadNode &node = static_cast(*dest); + if (-node.GetRegIdx() == kSregSp) { + spBased = true; + } + } + return spBased; +} + RegOperand &AArch64CGFunc::GetOrCreateResOperand(const BaseNode &parent, PrimType primType) { RegOperand *resOpnd = nullptr; if (parent.GetOpCode() == OP_regassign) { @@ -156,8 +169,7 @@ RegOperand &AArch64CGFunc::GetOrCreateResOperand(const BaseNode &parent, PrimTyp PregIdx pregIdx = regAssignNode.GetRegIdx(); if (IsSpecialPseudoRegister(pregIdx)) { /* if it is one of special registers */ - ASSERT(-pregIdx != kSregRetval0, "the dest of RegAssign node must not be kSregRetval0"); - resOpnd = &GetOrCreateSpecialRegisterOperand(-pregIdx); + resOpnd = &GetOrCreateSpecialRegisterOperand(-pregIdx, primType); } else { resOpnd = &GetOrCreateVirtualRegisterOperand(GetVirtualRegNOFromPseudoRegIdx(pregIdx)); } @@ -1400,9 +1412,7 @@ void AArch64CGFunc::SelectRegassign(RegassignNode &stmt, Operand &opnd0) { RegOperand *regOpnd = nullptr; PregIdx pregIdx = stmt.GetRegIdx(); if (IsSpecialPseudoRegister(pregIdx)) { - /* if it is one of special registers */ - ASSERT(-pregIdx != kSregRetval0, "the dest of RegAssign node must not be kSregRetval0"); - regOpnd = &GetOrCreateSpecialRegisterOperand(-pregIdx); + regOpnd = &GetOrCreateSpecialRegisterOperand(-pregIdx, stmt.GetPrimType()); } else { regOpnd = &GetOrCreateVirtualRegisterOperand(GetVirtualRegNOFromPseudoRegIdx(pregIdx)); } @@ -1911,6 +1921,152 @@ void AArch64CGFunc::SelectIassignoff(IassignoffNode &stmt) { SelectCopy(memOpnd, destType, srcOpnd, destType); } +void AArch64CGFunc::SelectIassignfpoff(IassignFPoffNode &stmt, Operand &opnd) { + int32 offset = stmt.GetOffset(); + PrimType primType = stmt.GetPrimType(); + uint32 bitlen = GetPrimTypeSize(primType) * kBitsPerByte; + + Operand &srcOpnd = LoadIntoRegister(opnd, primType); + RegOperand *rfp = &GetOrCreatePhysicalRegisterOperand(RFP, k64BitSize, kRegTyInt); + OfstOperand *offsetOpnd = &CreateOfstOpnd(offset, k32BitSize); + MemOperand &memOpnd = GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, rfp, nullptr, offsetOpnd, nullptr); + MOperator mOp = PickStInsn(bitlen, primType); + Insn &store = GetCG()->BuildInstruction(mOp, srcOpnd, memOpnd); + GetCurBB()->AppendInsn(store); + //std::cout << "=======================>SelectIassignfpoff offset " << offset << "\n"; +} + +void AArch64CGFunc::SelectIassignspoff(PrimType pTy, int32 offset, Operand &opnd) { + if (GetLmbcArgInfo() == nullptr) { + LmbcArgInfo *p = memPool->New(*GetFuncScopeAllocator()); + SetLmbcArgInfo(p); + } + uint32 byteLen = GetPrimTypeSize(pTy); + uint32 bitLen = byteLen * kBitsPerByte; + RegType regTy = GetRegTyFromPrimTy(pTy); + int32 curRegArgs = GetLmbcArgsInRegs(regTy); + if (curRegArgs < k8ByteSize) { + RegOperand *res = &CreateVirtualRegisterOperand(NewVReg(regTy, byteLen)); + SelectCopy(*res, pTy, opnd, pTy); + SetLmbcArgInfo(res, pTy, offset, 1); + } + else { + /* Move into allocated space */ + Operand &memOpd = CreateMemOpnd(RSP, offset, byteLen); + Operand ® = LoadIntoRegister(opnd, pTy); + GetCurBB()->AppendInsn( + GetCG()->BuildInstruction(PickStInsn(bitLen, pTy), reg, memOpd)); + } + IncLmbcArgsInRegs(regTy); /* num of args in registers */ + IncLmbcTotalArgs(); /* num of args */ +} + +// Search for CALL/ICALL node, must be called from a blkassignoff node +MIRType *AArch64CGFunc::GetAggTyFromCallSite(StmtNode *stmt) { + for ( ; stmt != nullptr; stmt = stmt->GetNext()) { + if (stmt->GetOpCode() == OP_call || stmt->GetOpCode() == OP_icallproto) { + break; + } + } + CHECK_FATAL(stmt && (stmt->GetOpCode() == OP_call || stmt->GetOpCode() == OP_icallproto), + "blkassign sp not followed by call"); + int32 nargs = GetLmbcTotalArgs(); + MIRType *ty = nullptr; + if (stmt->GetOpCode() == OP_call) { + CallNode *callNode = static_cast(stmt); + MIRFunction *fn = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(callNode->GetPUIdx()); + if (fn->GetFormalCount() > 0) { + ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fn->GetNthParamTyIdx(nargs)); + } + } else { + /* OP_icall */ + IcallNode *icallNode = static_cast(stmt); + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(icallNode->GetRetTyIdx()); + MIRFuncType *fType = static_cast(type); + ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fType->GetNthParamType(nargs)); + } + CHECK_FATAL(ty->GetPrimType() == PTY_agg, "Type in lmbc function not agg"); + return ty; +} + +/* If blassign for argument, this function loads the agg arguments into + virtual registers, disregard if there is sufficient physicall call + registers. Argument > 16-bytes are copied to preset space and ptr + result is loaded into virtual register. + If blassign is not for argument, this function simply memcpy */ +void AArch64CGFunc::SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) +{ + if (GetLmbcArgInfo() == nullptr) { + LmbcArgInfo *p = memPool->New(*GetFuncScopeAllocator()); + SetLmbcArgInfo(p); + } + CHECK_FATAL(src->GetKind() == Operand::kOpdRegister, "blkassign src type not in register"); + PrimType pTy = PTY_i64; + uint32 size = bNode.blockSize; + if (bNode.blockSize <= k16ByteSize) { + if (bNode.blockSize <= k1ByteSize) { + pTy = PTY_i8; + } else if (bNode.blockSize <= k2ByteSize) { + pTy = PTY_i16; + } else if (bNode.blockSize <= k4ByteSize) { + pTy = PTY_i32; + } else if (bNode.blockSize > k8ByteSize) { + size = k8ByteSize; + } + } + + Operand *dest = HandleExpr(bNode, *bNode.Opnd(0)); + if (IsBlkassignForPush(bNode)) { + /* follow calling convention */ + AArch64reg regno = static_cast(static_cast(src)->GetRegisterNumber()); + MIRStructType *ty = static_cast(GetAggTyFromCallSite(&bNode)); + uint32 fpregs = FloatParamRegRequired(*ty, size); + if (fpregs > 0) { + /* pure floating point in agg */ + pTy = (size == k4ByteSize) ? PTY_f32 : PTY_f64; + for (uint32 i = 0; i < fpregs; i++) { + int s = (i == 0) ? 0 : (i * size); + MemOperand &mem = CreateMemOpnd(regno, s, size * kBitsPerByte); + RegOperand *res = &CreateVirtualRegisterOperand(NewVReg(kRegTyFloat, size)); + SelectCopy(*res, pTy, mem, pTy); + SetLmbcArgInfo(res, pTy, bNode.offset + s, fpregs - i); + IncLmbcArgsInRegs(kRegTyFloat); + } + IncLmbcTotalArgs(); + return; + } else if (bNode.blockSize <= k16ByteSize) { + /* integer/mixed types */ + MemOperand &mem = CreateMemOpnd(regno, 0, size * kBitsPerByte); + RegOperand *res = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, size)); + SelectCopy(*res, pTy, mem, pTy); + SetLmbcArgInfo(res, pTy, bNode.offset, 2); + IncLmbcArgsInRegs(kRegTyInt); + if (bNode.blockSize > k8ByteSize) { + MemOperand &mem = CreateMemOpnd(regno, k8ByteSize, size * kBitsPerByte); + RegOperand *res = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, size)); + SelectCopy(*res, pTy, mem, pTy); + SetLmbcArgInfo(res, pTy, bNode.offset + k8ByteSize, 1); + IncLmbcArgsInRegs(kRegTyInt); + } + IncLmbcTotalArgs(); + return; + } + } + /* pass on stack */ + RegOperand *regResult = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + std::vector opndVec; + opndVec.push_back(regResult); /* result */ + opndVec.push_back(PrepareMemcpyParamOpnd(bNode.offset, *dest));/* param 0 */ + opndVec.push_back(src); /* param 1 */ + opndVec.push_back(PrepareMemcpyParamOpnd(bNode.blockSize));/* param 2 */ + SelectLibCall("memcpy", opndVec, PTY_a64, PTY_a64); + if (IsBlkassignForPush(bNode)) { + SetLmbcArgInfo(static_cast(src), pTy, (int32)bNode.offset, 1); + IncLmbcArgsInRegs(kRegTyInt); + IncLmbcTotalArgs(); + } +} + void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) { ASSERT(stmt.Opnd(0) != nullptr, "null ptr check"); Operand &lhsAddrOpnd = LoadIntoRegister(AddrOpnd, stmt.Opnd(0)->GetPrimType()); @@ -2520,18 +2676,23 @@ void AArch64CGFunc::SelectAddrof(Operand &result, MemOperand &memOpnd, FieldID f } } -Operand *AArch64CGFunc::SelectAddrof(AddrofNode &expr, const BaseNode &parent) { +Operand *AArch64CGFunc::SelectAddrof(AddrofNode &expr, const BaseNode &parent, bool isAddrofoff) { MIRSymbol *symbol = GetFunction().GetLocalOrGlobalSymbol(expr.GetStIdx()); int32 offset = 0; - if (expr.GetFieldID() != 0) { - MIRStructType *structType = static_cast(symbol->GetType()); - /* with array of structs, it is possible to have nullptr */ - if (structType != nullptr) { - offset = GetBecommon().GetFieldOffset(*structType, expr.GetFieldID()).first; + AddrofoffNode &addrofoffExpr = static_cast(static_cast(expr)); + if (isAddrofoff) { + offset = addrofoffExpr.offset; + } else { + if (expr.GetFieldID() != 0) { + MIRStructType *structType = static_cast(symbol->GetType()); + /* with array of structs, it is possible to have nullptr */ + if (structType != nullptr) { + offset = GetBecommon().GetFieldOffset(*structType, expr.GetFieldID()).first; + } } } if ((symbol->GetStorageClass() == kScFormal) && (symbol->GetSKind() == kStVar) && - ((expr.GetFieldID() != 0) || + ((isAddrofoff == false && expr.GetFieldID() != 0) || (GetBecommon().GetTypeSize(symbol->GetType()->GetTypeIndex().GetIdx()) > k16ByteSize))) { /* * Struct param is copied on the stack by caller if struct size > 16. @@ -2584,10 +2745,14 @@ Operand *AArch64CGFunc::SelectAddrof(AddrofNode &expr, const BaseNode &parent) { return &result; } - SelectAddrof(result, CreateStImmOperand(*symbol, offset, 0), expr.GetFieldID()); + SelectAddrof(result, CreateStImmOperand(*symbol, offset, 0), isAddrofoff ? 0 : expr.GetFieldID()); return &result; } +Operand *AArch64CGFunc::SelectAddrofoff(AddrofoffNode &expr, const BaseNode &parent) { + return SelectAddrof(static_cast(static_cast(expr)), parent, true); +} + Operand &AArch64CGFunc::SelectAddrofFunc(AddroffuncNode &expr, const BaseNode &parent) { uint32 instrSize = static_cast(expr.SizeOfInstr()); PrimType primType = (instrSize == k8ByteSize) ? PTY_u64 : @@ -2650,6 +2815,96 @@ Operand *AArch64CGFunc::SelectIreadoff(const BaseNode &parent, IreadoffNode &ire return result; } +RegOperand *AArch64CGFunc::GenLmbcParamLoad(int32 offset, uint32 byteSize, RegType regType, PrimType primType) { + RegOperand *rfp = &GetOrCreatePhysicalRegisterOperand(RFP, k64BitSize, kRegTyInt); + OfstOperand *offsetOpnd = &CreateOfstOpnd(offset, k32BitSize); + uint32 bitlen = byteSize * kBitsPerByte; + MemOperand &memOpnd = GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, rfp, nullptr, offsetOpnd, nullptr); + RegOperand *result = &GetOrCreateVirtualRegisterOperand(NewVReg(regType, byteSize)); + MOperator mOp = PickLdInsn(bitlen, primType); + Insn &load = GetCG()->BuildInstruction(mOp, *result, memOpnd); + GetCurBB()->AppendInsn(load); + return result; +} + +Operand *AArch64CGFunc::SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) { + int32 offset = ireadoff.GetOffset(); + PrimType primType = ireadoff.GetPrimType(); + uint32 bytelen = GetPrimTypeSize(primType); + uint32 bitlen = bytelen * kBitsPerByte; + RegType regty = GetRegTyFromPrimTy(primType); + RegOperand *result = nullptr; + if (offset >= 0) { + LmbcFormalParamInfo *info = GetLmbcFormalParamInfo(offset); + if (info->GetPrimType() == PTY_agg) { + bool inVreg = (info->GetVregNO() > 0); + regno_t reg = inVreg ? info->GetVregNO() : info->GetRegNO(); + if (info->IsPureFloat()) { + if (reg == 0) { + primType = (info->GetFpSize() == k4ByteSize) ? PTY_f32 : PTY_f64; + result = GenLmbcParamLoad(offset, info->GetFpSize(), kRegTyFloat, primType); + } else { + CHECK_FATAL(((offset % info->GetFpSize()) == 0), "SelectIreadfpoff: pure float struct offset not aligned"); + reg += ((offset - info->GetOffset()) / info->GetFpSize()); + result = &GetOrCreatePhysicalRegisterOperand((AArch64reg)(reg), bitlen, regty); + } + } else { + if (reg == 0) { + result = GenLmbcParamLoad(offset, bytelen, regty, primType); + } else { + if (info->GetSize() > k16ByteSize) { + result = GenLmbcParamLoad(offset, bytelen, regty, primType); + } else if (bytelen == k8ByteSize) { + bool isSecondReg = (offset - info->GetOffset()) >= k8ByteSize; + reg += (isSecondReg ? kOneRegister : 0); + if (inVreg) { + result = &GetOrCreateVirtualRegisterOperand(reg); + } else { + result = &GetOrCreatePhysicalRegisterOperand((AArch64reg)(reg), bitlen, regty); + } + } else { + bool isSecondReg = (offset - info->GetOffset()) >= k8ByteSize; + reg += (isSecondReg ? kOneRegister : 0); + RegOperand *paramReg; + if (inVreg) { + paramReg = &GetOrCreateVirtualRegisterOperand(reg); + } else { + paramReg = &GetOrCreatePhysicalRegisterOperand((AArch64reg)(reg), k64BitSize, kRegTyInt); + } + RegOperand *extractReg = &GetOrCreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + uint32 lsbPos = ((isSecondReg ? (offset - k8ByteSize) : offset) - info->GetOffset()) * kBitsPerByte; + ImmOperand *lsb = &CreateImmOperand(lsbPos, k8BitSize, false); + ImmOperand *width = &CreateImmOperand(bitlen, k8BitSize, false); + MOperator mOp = /*(bytelen > k4ByteSize) ? */MOP_xubfxrri6i6/* : MOP_wubfxrri5i5*/; + Insn &extract = GetCG()->BuildInstruction(mOp, *extractReg, *paramReg, *lsb, *width); + GetCurBB()->AppendInsn(extract); + if (IsPrimitiveFloat(primType)) { + mOp = (bytelen > k4ByteSize) ? MOP_xvmovdr : MOP_xvmovsr; + result = &GetOrCreateVirtualRegisterOperand(NewVReg(regty, bytelen)); + Insn &mov = GetCG()->BuildInstruction(mOp, *result, *extractReg); + GetCurBB()->AppendInsn(mov); + } else { + result = extractReg; + } + } + } + } + } else { + CHECK_FATAL(primType == info->GetPrimType(), "Incorrect primtype"); + CHECK_FATAL(offset == info->GetOffset(), "Incorrect offset"); + if (info->GetRegNO() == 0) { + /* TODO : follow lmbc sp offset for now */ + result = GenLmbcParamLoad(offset, bytelen, regty, primType); + } else { + result = &GetOrCreatePhysicalRegisterOperand((AArch64reg)(info->GetRegNO()), bitlen, regty); + } + } + } else { + result = GenLmbcParamLoad(offset, bytelen, regty, primType); + } + return result; +} + Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int extraOffset, PrimType finalBitFieldDestType) { int32 offset = 0; @@ -3268,9 +3523,7 @@ Operand *AArch64CGFunc::SelectAdd(BinaryNode &node, Operand &opnd0, Operand &opn auto ®AssignNode = static_cast(parent); PregIdx pregIdx = regAssignNode.GetRegIdx(); if (IsSpecialPseudoRegister(pregIdx)) { - /* if it is one of special registers */ - ASSERT(-pregIdx != kSregRetval0, "the dest of RegAssign node must not be kSregRetval0"); - resOpnd = &GetOrCreateSpecialRegisterOperand(-pregIdx); + resOpnd = &GetOrCreateSpecialRegisterOperand(-pregIdx, dtype); } else { resOpnd = &GetOrCreateVirtualRegisterOperand(GetVirtualRegNOFromPseudoRegIdx(pregIdx)); } @@ -5862,6 +6115,99 @@ void AArch64CGFunc::GenerateCleanupCode(BB &bb) { SetCleanupBB(*GetCurBB()); } +uint32 AArch64CGFunc::FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) { + AArch64CallConvImpl parmlocator(GetBecommon()); + return parmlocator.FloatParamRegRequired(structType, fpSize); +} + +/* + * Map param registers to formals. For small structs passed in param registers, + * create a move to vreg since lmbc IR does not create a regassign for them. + */ +void AArch64CGFunc::AssignLmbcFormalParams() { + PrimType primType; + uint32 offset; + regno_t intReg = R0; + regno_t fpReg = V0; + for (auto param : GetLmbcParamVec()) { + primType = param->GetPrimType(); + offset = param->GetOffset(); + if (IsPrimitiveInteger(primType)) { + if (intReg > R7) { + param->SetRegNO(0); + } else { + param->SetRegNO(intReg); + intReg++; + } + } else if (IsPrimitiveFloat(primType)) { + if (fpReg > V7) { + param->SetRegNO(0); + } else { + param->SetRegNO(fpReg); + fpReg++; + } + } else if (primType == PTY_agg) { + if (param->IsPureFloat()) { + uint32 numFpRegs = param->GetNumRegs(); + if ((fpReg + numFpRegs - kOneRegister) > V7) { + param->SetRegNO(0); + } else { + param->SetRegNO(fpReg); + fpReg += numFpRegs; + } + } else if (param->GetSize() > k16ByteSize) { + if (intReg > R7) { + param->SetRegNO(0); + } else { + param->SetRegNO(intReg); + intReg++; + } + } else if (param->GetSize() <= k8ByteSize) { + if (intReg > R7) { + param->SetRegNO(0); + } else { + param->SetRegNO(intReg); + intReg++; + } + } else { + /* size > 8 && size <= 16 */ + if ((intReg + kOneRegister) > R7) { + param->SetRegNO(0); + } else { + param->SetRegNO(intReg); + param->SetNumRegs(kTwoRegister); + intReg += kTwoRegister; + } + } + if (param->GetRegNO() != 0) { + for (int i = 0; i < param->GetNumRegs(); ++i) { + PrimType pType = PTY_i64; + RegType rType = kRegTyInt; + uint32 rSize = k8ByteSize; + if (param->IsPureFloat()) { + rType = kRegTyFloat; + if (param->GetFpSize() <= k4ByteSize) { + pType = PTY_f32; + rSize = k4ByteSize; + } else { + pType = PTY_f64; + } + } + regno_t vreg = NewVReg(rType, rSize); + RegOperand &dest = GetOrCreateVirtualRegisterOperand(vreg); + RegOperand &src = GetOrCreatePhysicalRegisterOperand(static_cast(param->GetRegNO() + i), rSize * kBitsPerByte, rType); + SelectCopy(dest, pType, src, pType); + if (param->GetVregNO() == 0) { + param->SetVregNO(vreg); + } + } + } + } else { + CHECK_FATAL(false, "lmbc formal primtype not handled"); + } + } +} + /* if offset < 0, allocation; otherwise, deallocation */ MemOperand &AArch64CGFunc::CreateCallFrameOperand(int32 offset, int32 size) { MemOperand *memOpnd = CreateStackMemOpnd(RSP, offset, size); @@ -5881,7 +6227,13 @@ AArch64CGFunc::MovkLslOperandArray AArch64CGFunc::movkLslOperands = { LogicalShiftLeftOperand AArch64CGFunc::addSubLslOperand(kShiftAmount12, 4); MemOperand &AArch64CGFunc::CreateStkTopOpnd(uint32 offset, uint32 size) { - MemOperand *memOp = CreateStackMemOpnd(RFP, offset, size); + AArch64reg reg; + if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + reg = RSP; + } else { + reg = RFP; + } + MemOperand *memOp = CreateStackMemOpnd(reg, offset, size); return *memOp; } @@ -7684,6 +8036,46 @@ void AArch64CGFunc::IntrinsifyStringIndexOf(ListOperand &srcOpnds, const MIRSymb callBB->AppendBB(*jointBB); SetCurBB(*jointBB); } + +/* Lmbc calls have no argument, they are all explicit iassignspoff or + blkassign. Info collected and to be emitted here */ +void AArch64CGFunc::LmbcSelectParmList(ListOperand *srcOpnds) { + if (GetLmbcArgInfo() == nullptr) { + return; /* no arg */ + } + CHECK_FATAL(GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc, "To be called for Lmbc model only"); + MapleVector &args = GetLmbcCallArgs(); + MapleVector &types = GetLmbcCallArgTypes(); + MapleVector &offsets = GetLmbcCallArgOffsets(); + MapleVector ®s = GetLmbcCallArgNumOfRegs(); + int iCnt = 0; + int fCnt = 0; + for (int i = 0; i < args.size(); i++) { + RegType ty = args[i]->GetRegisterType(); + PrimType pTy = types[i]; + if ((i + regs[i]) <= k8ByteSize) { + AArch64reg reg; + if (args[i]->IsOfIntClass() ) { + reg = static_cast(R0 + iCnt++); + } else { + reg = static_cast(V0 + fCnt++); + } + RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(pTy) * kBitsPerByte, ty); + SelectCopy(*res, pTy, *args[i], pTy); + srcOpnds->PushOpnd(*res); + } else { + int32 pSize = GetPrimTypeSize(pTy); + Operand &memOpd = CreateMemOpnd(RSP, offsets[i], pSize); + GetCurBB()->AppendInsn( + GetCG()->BuildInstruction( + PickStInsn(pSize * kBitsPerByte, pTy), *args[i], memOpd)); + } + } + ResetLmbcArgInfo(); /* reset */ + ResetLmbcArgsInRegs(); + ResetLmbcTotalArgs(); +} + void AArch64CGFunc::SelectCall(CallNode &callNode) { MIRFunction *fn = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(callNode.GetPUIdx()); MIRSymbol *fsym = GetFunction().GetLocalOrGlobalSymbol(fn->GetStIdx(), false); @@ -7695,6 +8087,9 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) { } ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); + if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + LmbcSelectParmList(srcOpnds); + } bool callNative = false; if ((fsym->GetName() == "MCC_CallFastNative") || (fsym->GetName() == "MCC_CallFastNativeExt") || (fsym->GetName() == "MCC_CallSlowNative0") || (fsym->GetName() == "MCC_CallSlowNative1") || @@ -7760,7 +8155,11 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) { void AArch64CGFunc::SelectIcall(IcallNode &icallNode, Operand &srcOpnd) { ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); - SelectParmList(icallNode, *srcOpnds); + if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + LmbcSelectParmList(srcOpnds); + } else { + SelectParmList(icallNode, *srcOpnds); + } Operand *fptrOpnd = &srcOpnd; if (fptrOpnd->GetKind() != Operand::kOpdRegister) { @@ -7826,8 +8225,7 @@ void AArch64CGFunc::SelectReturn(Operand *opnd0) { AArch64CallConvImpl retLocator(GetBecommon()); CCLocInfo retMech; retLocator.InitReturnInfo(*retTyp, retMech); - if (retMech.GetRegCount() > 0) { - CHECK_FATAL(opnd0 != nullptr, "opnd0 must not be nullptr"); + if ((retMech.GetRegCount() > 0) && (opnd0 != nullptr)) { RegType regTyp = is64x1vec ? kRegTyFloat : GetRegTyFromPrimTy(retMech.GetPrimTypeOfReg0()); PrimType oriPrimType = is64x1vec ? GetFunction().GetReturnType()->GetPrimType() : retMech.GetPrimTypeOfReg0(); AArch64reg retReg = static_cast(retMech.GetReg0()); @@ -7862,8 +8260,6 @@ void AArch64CGFunc::SelectReturn(Operand *opnd0) { } else { CHECK_FATAL(false, "nyi"); } - } else if (opnd0 != nullptr) { /* pass in memory */ - CHECK_FATAL(false, "SelectReturn: return in memory NYI"); } GetExitBBsVec().emplace_back(GetCurBB()); } @@ -7877,6 +8273,9 @@ RegOperand &AArch64CGFunc::GetOrCreateSpecialRegisterOperand(PregIdx sregIdx, Pr case kSregFp: reg = RFP; break; + case kSregGp: + reg = RFP; + break; case kSregThrownval: { /* uses x0 == R0 */ ASSERT(uCatch.regNOCatch > 0, "regNOCatch should greater than 0."); if (Globals::GetInstance()->GetOptimLevel() == 0) { diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp index 13c7522194..9572204d34 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp @@ -189,6 +189,16 @@ void AArch64MemLayout::LayoutVarargParams() { } void AArch64MemLayout::LayoutFormalParams() { + if (be.GetMIRModule().GetFlavor() == kFlavorLmbc && mirFunction->GetFormalCount() == 0) { + /* + * lmbc : upformalsize - size of formals passed from caller's frame into current function + * framesize - total frame size of current function used by Maple IR + * outparmsize - portion of frame size of current function used by call parameters + */ + segArgsStkPassed.SetSize(mirFunction->GetOutParmSize()); + return; + } + AArch64CallConvImpl parmLocator(be); CCLocInfo ploc; for (size_t i = 0; i < mirFunction->GetFormalCount(); ++i) { @@ -274,6 +284,11 @@ void AArch64MemLayout::LayoutFormalParams() { } void AArch64MemLayout::LayoutLocalVariables(std::vector &tempVar, std::vector &returnDelays) { + if (be.GetMIRModule().GetFlavor() == kFlavorLmbc && mirFunction->GetFormalCount() == 0) { + segLocals.SetSize(mirFunction->GetFrameSize() - mirFunction->GetOutParmSize()); + return; + } + uint32 symTabSize = mirFunction->GetSymTab()->GetSymbolTableSize(); for (uint32 i = 0; i < symTabSize; ++i) { MIRSymbol *sym = mirFunction->GetSymTab()->GetSymbolFromStIdx(i); diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp index 2d4da9a038..9f1ae84cd8 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp @@ -22,6 +22,11 @@ void AArch64FPLROffsetAdjustment::Run() { } void AArch64FPLROffsetAdjustment::AdjustmentOffsetForOpnd(Insn &insn, AArch64CGFunc &aarchCGFunc) { + if (aarchCGFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + /* TODO: Need to handle */ + AdjustmentStackPointer(insn, aarchCGFunc); + return; + } uint32 opndNum = insn.GetOperandSize(); MemLayout *memLayout = aarchCGFunc.GetMemlayout(); bool stackBaseOpnd = false; diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp index f4143111c0..59e44f6e28 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp @@ -185,6 +185,9 @@ void AArch64GenProEpilog::TailCallBBOpt(BB &bb, std::set &callInsns, BB & * Return value: true if function do not need Prologue/Epilogue. false otherwise. */ bool AArch64GenProEpilog::TailCallOpt() { + if (cgFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + return false; + } /* Count how many call insns in the whole function. */ uint32 nCount = 0; bool hasGetStackClass = false; @@ -1205,9 +1208,16 @@ void AArch64GenProEpilog::GeneratePushRegs() { Operand &spOpnd = aarchCGFunc.GetOrCreatePhysicalRegisterOperand(RSP, k64BitSize, kRegTyInt); Operand &fpOpnd = aarchCGFunc.GetOrCreatePhysicalRegisterOperand(stackBaseReg, k64BitSize, kRegTyInt); int64 argsToStkPassSize = cgFunc.GetMemlayout()->SizeOfArgsToStackPass(); - if (argsToStkPassSize > 0) { - Operand &immOpnd = aarchCGFunc.CreateImmOperand(argsToStkPassSize, k32BitSize, true); - aarchCGFunc.SelectAdd(fpOpnd, spOpnd, immOpnd, PTY_u64); + bool isLmbc = cgFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc; + if ((argsToStkPassSize > 0) || isLmbc) { + Operand *immOpnd; + if (isLmbc) { + int32 size = static_cast(static_cast(cgFunc.GetMemlayout())->RealStackFrameSize()); + immOpnd = &aarchCGFunc.CreateImmOperand(size, k32BitSize, true); + } else { + immOpnd = &aarchCGFunc.CreateImmOperand(argsToStkPassSize, k32BitSize, true); + } + aarchCGFunc.SelectAdd(fpOpnd, spOpnd, *immOpnd, PTY_u64); cgFunc.GetCurBB()->GetLastInsn()->SetFrameDef(true); if (cgFunc.GenCfi()) { cgFunc.GetCurBB()->AppendInsn(aarchCGFunc.CreateCfiDefCfaInsn(stackBaseReg, @@ -1423,10 +1433,17 @@ void AArch64GenProEpilog::GenerateProlog(BB &bb) { } if (useFP) { Operand &fpOpnd = aarchCGFunc.GetOrCreatePhysicalRegisterOperand(stackBaseReg, k64BitSize, kRegTyInt); + bool isLmbc = cgFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc; int64 argsToStkPassSize = cgFunc.GetMemlayout()->SizeOfArgsToStackPass(); - if (argsToStkPassSize > 0) { - Operand &immOpnd = aarchCGFunc.CreateImmOperand(argsToStkPassSize, k32BitSize, true); - aarchCGFunc.SelectAdd(fpOpnd, spOpnd, immOpnd, PTY_u64); + if ((argsToStkPassSize > 0) || isLmbc) { + Operand *immOpnd; + if (isLmbc) { + int32 size = static_cast(static_cast(cgFunc.GetMemlayout())->RealStackFrameSize()); + immOpnd = &aarchCGFunc.CreateImmOperand(size, k32BitSize, true); + } else { + immOpnd = &aarchCGFunc.CreateImmOperand(argsToStkPassSize, k32BitSize, true); + } + aarchCGFunc.SelectAdd(fpOpnd, spOpnd, *immOpnd, PTY_u64); cgFunc.GetCurBB()->GetLastInsn()->SetFrameDef(true); if (cgFunc.GenCfi()) { cgFunc.GetCurBB()->AppendInsn(aarchCGFunc.CreateCfiDefCfaInsn( @@ -1821,7 +1838,7 @@ void AArch64GenProEpilog::GenerateEpilog(BB &bb) { } if (cgFunc.HasVLAOrAlloca()) { - auto size = static_cast(cgFunc.GetMemlayout())->GetSegArgsStkPass().GetSize(); + auto size = static_cast(cgFunc.GetMemlayout())->GetSegArgsToStkPass().GetSize(); stackFrameSize = stackFrameSize < size ? 0 : stackFrameSize - size; } diff --git a/src/mapleall/maple_be/src/cg/cg_phasemanager.cpp b/src/mapleall/maple_be/src/cg/cg_phasemanager.cpp index 47660be46c..f8e5c766fd 100644 --- a/src/mapleall/maple_be/src/cg/cg_phasemanager.cpp +++ b/src/mapleall/maple_be/src/cg/cg_phasemanager.cpp @@ -259,7 +259,9 @@ bool CgFuncPM::PhaseRun(MIRModule &m) { (void)cf.Simplify(mirFunc->GetBody()); } - DoFuncCGLower(m, *mirFunc); + if (m.GetFlavor() != MIRFlavor::kFlavorLmbc) { + DoFuncCGLower(m, *mirFunc); + } /* create CGFunc */ MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(mirFunc->GetStIdx().Idx()); auto funcMp = std::make_unique(memPoolCtrler, funcSt->GetName()); diff --git a/src/mapleall/maple_be/src/cg/cgfunc.cpp b/src/mapleall/maple_be/src/cg/cgfunc.cpp index 883bb5f360..44dd726b1e 100644 --- a/src/mapleall/maple_be/src/cg/cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/cgfunc.cpp @@ -184,6 +184,11 @@ Operand *HandleAddrof(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) { return cgFunc.SelectAddrof(addrofNode, parent); } +Operand *HandleAddrofoff(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) { + auto &addrofoffNode = static_cast(expr); + return cgFunc.SelectAddrofoff(addrofoffNode, parent); +} + Operand *HandleAddroffunc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) { auto &addroffuncNode = static_cast(expr); return &cgFunc.SelectAddrofFunc(addroffuncNode, parent); @@ -204,6 +209,11 @@ Operand *HandleIreadoff(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) return cgFunc.SelectIreadoff(parent, ireadNode); } +Operand *HandleIreadfpoff(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) { + auto &ireadNode = static_cast(expr); + return cgFunc.SelectIreadfpoff(parent, ireadNode); +} + Operand *HandleSub(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) { return cgFunc.SelectSub(static_cast(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent); @@ -964,10 +974,12 @@ void InitHandleExprFactory() { RegisterFactoryFunction(OP_div, HandleDiv); RegisterFactoryFunction(OP_rem, HandleRem); RegisterFactoryFunction(OP_addrof, HandleAddrof); + RegisterFactoryFunction(OP_addrofoff, HandleAddrofoff); RegisterFactoryFunction(OP_addroffunc, HandleAddroffunc); RegisterFactoryFunction(OP_addroflabel, HandleAddrofLabel); RegisterFactoryFunction(OP_iread, HandleIread); RegisterFactoryFunction(OP_ireadoff, HandleIreadoff); + RegisterFactoryFunction(OP_ireadfpoff, HandleIreadfpoff); RegisterFactoryFunction(OP_sub, HandleSub); RegisterFactoryFunction(OP_band, HandleBand); RegisterFactoryFunction(OP_bior, HandleBior); @@ -1243,6 +1255,28 @@ void HandleIassignoff(StmtNode &stmt, CGFunc &cgFunc) { cgFunc.SelectIassignoff(iassignoffNode); } +void HandleIassignfpoff(StmtNode &stmt, CGFunc &cgFunc) { + ASSERT(stmt.GetOpCode() == OP_iassignfpoff, "expect iassignfpoff"); + auto &iassignfpoffNode = static_cast(stmt); + cgFunc.SelectIassignfpoff(iassignfpoffNode, *cgFunc.HandleExpr(stmt, *stmt.Opnd(0))); +} + +void HandleIassignspoff(StmtNode &stmt, CGFunc &cgFunc) { + ASSERT(stmt.GetOpCode() == OP_iassignspoff, "expect iassignspoff"); + auto &baseNode = static_cast(stmt); /* same as FP */ + BaseNode *rhs = baseNode.GetRHS(); + ASSERT(rhs != nullptr, "get rhs of iassignspoffNode failed"); + Operand *opnd0 = cgFunc.HandleExpr(baseNode, *rhs); + cgFunc.SelectIassignspoff(baseNode.GetPrimType(), baseNode.GetOffset(), *opnd0); +} + +void HandleBlkassignoff(StmtNode &stmt, CGFunc &cgFunc) { + ASSERT(stmt.GetOpCode() == OP_blkassignoff, "expect blkassignoff"); + auto &baseNode = static_cast(stmt); + Operand *src = cgFunc.HandleExpr(baseNode, *baseNode.Opnd(1)); + cgFunc.SelectBlkassignoff(baseNode, src); +} + void HandleEval(const StmtNode &stmt, CGFunc &cgFunc) { (void)cgFunc.HandleExpr(stmt, *static_cast(stmt).Opnd(0)); } @@ -1314,6 +1348,7 @@ void InitHandleStmtFactory() { RegisterFactoryFunction(OP_return, HandleReturn); RegisterFactoryFunction(OP_call, HandleCall); RegisterFactoryFunction(OP_icall, HandleICall); + RegisterFactoryFunction(OP_icallproto, HandleICall); RegisterFactoryFunction(OP_intrinsiccall, HandleIntrinCall); RegisterFactoryFunction(OP_intrinsiccallassigned, HandleIntrinCall); RegisterFactoryFunction(OP_intrinsiccallwithtype, HandleIntrinCall); @@ -1323,6 +1358,9 @@ void InitHandleStmtFactory() { RegisterFactoryFunction(OP_regassign, HandleRegassign); RegisterFactoryFunction(OP_iassign, HandleIassign); RegisterFactoryFunction(OP_iassignoff, HandleIassignoff); + RegisterFactoryFunction(OP_iassignfpoff, HandleIassignfpoff); + RegisterFactoryFunction(OP_iassignspoff, HandleIassignspoff); + RegisterFactoryFunction(OP_blkassignoff, HandleBlkassignoff); RegisterFactoryFunction(OP_eval, HandleEval); RegisterFactoryFunction(OP_rangegoto, HandleRangeGoto); RegisterFactoryFunction(OP_membarrelease, HandleMembar); @@ -1367,6 +1405,7 @@ CGFunc::CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, lrVec(allocator.Adapter()), #endif /* TARGARM32 */ loops(allocator.Adapter()), + lmbcParamVec(allocator.Adapter()), shortFuncName(cg.ExtractFuncName(mirFunc.GetName()) + "." + std::to_string(funcId), &memPool) { mirModule.SetCurFunction(&func); dummyBB = CreateNewBB(); @@ -1499,11 +1538,99 @@ int32 CGFunc::GetFreqFromStmt(uint32 stmtId) { return GetFunction().GetFreqFromFirstStmt(stmtId); } +LmbcFormalParamInfo *CGFunc::GetLmbcFormalParamInfo(uint32 offset) { + MapleVector ¶mVec = GetLmbcParamVec(); + for (auto *param : paramVec) { + uint32 paramOffset = param->GetOffset(); + uint32 paramSize = param->GetSize(); + if (paramOffset <= offset && offset < (paramOffset + paramSize)) { + return param; + } + } + return nullptr; +} + +/* + * For formals of lmbc, the formal list is deleted if there is no + * passing of aggregate by value. + */ +void CGFunc::CreateLmbcFormalParamInfo() { + if (GetMirModule().GetFlavor() != MIRFlavor::kFlavorLmbc) { + return; + } + PrimType primType; + uint32 offset; + uint32 typeSize; + MIRFunction &func = GetFunction(); + if (func.GetParamSize() > 0) { + int stackOffset = 0; + for (size_t idx = 0; idx < func.GetParamSize(); ++idx) { + MIRSymbol *sym = func.GetFormal(idx); + MIRType *type; + TyIdx tyIdx; + if (sym) { + tyIdx = func.GetNthParamTyIdx(idx); + type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx); + } else { + FormalDef vec = const_cast(GetBecommon().GetMIRModule().CurFunction())->GetFormalDefAt(idx); + tyIdx = vec.formalTyIdx; + type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx); + } + primType = type->GetPrimType(); + offset = stackOffset; + typeSize = GetBecommon().GetTypeSize(tyIdx); + stackOffset += (typeSize + 7) & (-8); + LmbcFormalParamInfo *info = GetMemoryPool()->New(primType, offset, typeSize); + lmbcParamVec.push_back(info); + if (type->GetKind() == kTypeStruct) { + MIRStructType &structType = static_cast(*type); + uint32 fpSize; + uint32 numFpRegs = FloatParamRegRequired(structType, fpSize); + if (numFpRegs > 0) { + info->SetIsPureFloat(); + info->SetNumRegs(numFpRegs); + info->SetFpSize(fpSize); + } + } + } + } else { + /* No aggregate pass by value here */ + for (StmtNode *stmt = func.GetBody()->GetFirst(); stmt != nullptr; stmt = stmt->GetNext()) { + if (stmt == nullptr) { + break; + } + if (stmt->GetOpCode() == OP_label) { + continue; + } + if (stmt->GetOpCode() != OP_regassign) { + break; + } + RegassignNode *regAssignNode = static_cast(stmt); + BaseNode *operand = regAssignNode->Opnd(0); + if (operand->GetOpCode() != OP_ireadfpoff) { + break; + } + IreadFPoffNode *ireadNode = static_cast(operand); + primType = ireadNode->GetPrimType(); + offset = ireadNode->GetOffset(); + typeSize = GetPrimTypeSize(primType); CHECK_FATAL((offset % k8ByteSize) == 0, ""); // scalar only, no struct for now + LmbcFormalParamInfo *info = GetMemoryPool()->New(primType, offset, typeSize); + lmbcParamVec.push_back(info); + } + } + std::sort(lmbcParamVec.begin(), lmbcParamVec.end(), + [] (LmbcFormalParamInfo *x, LmbcFormalParamInfo *y) + { return x->GetOffset() < y->GetOffset(); } + ); + AssignLmbcFormalParams(); +} + void CGFunc::GenerateInstruction() { InitHandleExprFactory(); InitHandleStmtFactory(); StmtNode *secondStmt = HandleFirstStmt(); + CreateLmbcFormalParamInfo(); /* First Pass: Creates the doubly-linked list of BBs (next,prev) */ volReleaseInsn = nullptr; unsigned lastSrcLoc = 0; -- Gitee From 5e9a0d51b75fea3103f6a99441af8f87f6eca2f3 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Fri, 22 Apr 2022 20:04:18 -0700 Subject: [PATCH 2/4] Define new opcode icallproto that provides the prototype in the instruction icallproto is the lowered form of icall formed by LMBCLowerer. Without this, mplcg would not be able to get the function prototype of the function pointer used in icall in lmbc. --- src/mapleall/maple_ir/include/mir_nodes.h | 3 +- src/mapleall/maple_ir/include/mir_parser.h | 3 +- src/mapleall/maple_ir/include/opcodes.def | 1 + src/mapleall/maple_ir/src/bin_func_export.cpp | 1 + src/mapleall/maple_ir/src/bin_func_import.cpp | 1 + src/mapleall/maple_ir/src/bin_mpl_import.cpp | 1 - src/mapleall/maple_ir/src/mir_nodes.cpp | 11 ++- src/mapleall/maple_ir/src/mir_parser.cpp | 24 ++++-- src/mapleall/maple_me/include/lmbc_lower.h | 1 + src/mapleall/maple_me/src/lmbc_lower.cpp | 79 ++++++++++++++++++- 10 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/mapleall/maple_ir/include/mir_nodes.h b/src/mapleall/maple_ir/include/mir_nodes.h index 32733614cb..8cc6689c26 100755 --- a/src/mapleall/maple_ir/include/mir_nodes.h +++ b/src/mapleall/maple_ir/include/mir_nodes.h @@ -3216,6 +3216,7 @@ class CallNode : public NaryStmtNode { CallReturnVector returnValues; }; +// icall and icallproto class IcallNode : public NaryStmtNode { public: IcallNode(MapleAllocator &allocator, Opcode o) @@ -3291,7 +3292,7 @@ class IcallNode : public NaryStmtNode { } private: - TyIdx retTyIdx; // return type for callee + TyIdx retTyIdx; // for icall: return type for callee; for icallproto: the prototye // the 0th operand is the function pointer CallReturnVector returnValues; }; diff --git a/src/mapleall/maple_ir/include/mir_parser.h b/src/mapleall/maple_ir/include/mir_parser.h index 249b619b07..d05c844f31 100755 --- a/src/mapleall/maple_ir/include/mir_parser.h +++ b/src/mapleall/maple_ir/include/mir_parser.h @@ -125,9 +125,10 @@ class MIRParser { PUIdx EnterUndeclaredFunction(bool isMcount = false); // for -pg in order to add "void _mcount()" bool ParseStmtCall(StmtNodePtr&); bool ParseStmtCallMcount(StmtNodePtr&); // for -pg in order to add "void _mcount()" to all the functions - bool ParseStmtIcall(StmtNodePtr&, bool isAssigned); + bool ParseStmtIcall(StmtNodePtr&, Opcode op); bool ParseStmtIcall(StmtNodePtr&); bool ParseStmtIcallassigned(StmtNodePtr&); + bool ParseStmtIcallproto(StmtNodePtr&); bool ParseStmtIntrinsiccall(StmtNodePtr&, bool isAssigned); bool ParseStmtIntrinsiccall(StmtNodePtr&); bool ParseStmtIntrinsiccallassigned(StmtNodePtr&); diff --git a/src/mapleall/maple_ir/include/opcodes.def b/src/mapleall/maple_ir/include/opcodes.def index d1265eda42..34cfb51c8d 100755 --- a/src/mapleall/maple_ir/include/opcodes.def +++ b/src/mapleall/maple_ir/include/opcodes.def @@ -220,3 +220,4 @@ OPCODE(dassignoff, DassignoffNode, (OPCODEISSTMT | OPCODEHASSSADEF), 8) OPCODE(iassignspoff, IassignFPoffNode, OPCODEISSTMT, 8) OPCODE(blkassignoff, BlkassignoffNode, OPCODEISSTMT, 8) + OPCODE(icallproto, IcallNode, (OPCODEISSTMT | OPCODEISVARSIZE | OPCODEHASSSAUSE | OPCODEHASSSADEF | OPCODEISCALL), 8) diff --git a/src/mapleall/maple_ir/src/bin_func_export.cpp b/src/mapleall/maple_ir/src/bin_func_export.cpp index 843a7693ca..5117ed8ed0 100644 --- a/src/mapleall/maple_ir/src/bin_func_export.cpp +++ b/src/mapleall/maple_ir/src/bin_func_export.cpp @@ -493,6 +493,7 @@ void BinaryMplExport::OutputBlockNode(BlockNode *block) { WriteNum(static_cast(s->NumOpnds())); break; } + case OP_icallproto: case OP_icall: { IcallNode *icallnode = static_cast(s); OutputTypeViaTypeName(icallnode->GetRetTyIdx()); diff --git a/src/mapleall/maple_ir/src/bin_func_import.cpp b/src/mapleall/maple_ir/src/bin_func_import.cpp index f956ed2070..d18aac9f58 100644 --- a/src/mapleall/maple_ir/src/bin_func_import.cpp +++ b/src/mapleall/maple_ir/src/bin_func_import.cpp @@ -632,6 +632,7 @@ BlockNode *BinaryMplImport::ImportBlockNode(MIRFunction *func) { stmt = s; break; } + case OP_icallproto: case OP_icall: { IcallNode *s = func->GetCodeMemPool()->New(mod, op); s->SetRetTyIdx(ImportType()); diff --git a/src/mapleall/maple_ir/src/bin_mpl_import.cpp b/src/mapleall/maple_ir/src/bin_mpl_import.cpp index 4e2ede0ce6..0406ce7478 100644 --- a/src/mapleall/maple_ir/src/bin_mpl_import.cpp +++ b/src/mapleall/maple_ir/src/bin_mpl_import.cpp @@ -818,7 +818,6 @@ TyIdx BinaryMplImport::ImportTypeNonJava() { type.GetParamAttrsList().push_back(ImportTypeAttrs()); } GlobalTables::GetTypeTable().CreateMirTypeNodeAt(type, tyIdxUsed, &mod, false, false); - CHECK_FATAL(type.GetRetTyIdx() != TyIdx(0), "ImportTypeNonJava: retTyIdx cannot be 0"); return tyIdxUsed; } case kBinKindTypeParam: { diff --git a/src/mapleall/maple_ir/src/mir_nodes.cpp b/src/mapleall/maple_ir/src/mir_nodes.cpp index f60a392b3b..92f41d11fc 100755 --- a/src/mapleall/maple_ir/src/mir_nodes.cpp +++ b/src/mapleall/maple_ir/src/mir_nodes.cpp @@ -1128,7 +1128,12 @@ void CallNode::Dump(int32 indent, bool newline) const { } MIRType *IcallNode::GetCallReturnType() { - return GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx); + if (op == OP_icall || op == OP_icallassigned) { + return GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx); + } + // icallproto + MIRFuncType *funcType = static_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx)); + return GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetRetTyIdx()); } const MIRSymbol *IcallNode::GetCallReturnSymbol(const MIRModule &mod) const { @@ -1150,6 +1155,10 @@ const MIRSymbol *IcallNode::GetCallReturnSymbol(const MIRModule &mod) const { void IcallNode::Dump(int32 indent, bool newline) const { StmtNode::DumpBase(indent); + if (op == OP_icallproto) { + LogInfo::MapleLogger() << " "; + GlobalTables::GetTypeTable().GetTypeFromTyIdx(retTyIdx)->Dump(indent + 1); + } NaryOpnds::Dump(indent); if (kOpcodeInfo.IsCallAssigned(GetOpCode())) { DumpCallReturns(*theMIRModule, this->returnValues, indent); diff --git a/src/mapleall/maple_ir/src/mir_parser.cpp b/src/mapleall/maple_ir/src/mir_parser.cpp index 752dba35cd..2da0b1da7a 100755 --- a/src/mapleall/maple_ir/src/mir_parser.cpp +++ b/src/mapleall/maple_ir/src/mir_parser.cpp @@ -922,22 +922,31 @@ bool MIRParser::ParseStmtCall(StmtNodePtr &stmt) { return true; } -bool MIRParser::ParseStmtIcall(StmtNodePtr &stmt, bool isAssigned) { +bool MIRParser::ParseStmtIcall(StmtNodePtr &stmt, Opcode op) { // syntax: icall (, , ..., ) // icallassigned (, ..., ) { // dassign // dassign // . . . // dassign } - auto *iCallStmt = mod.CurFuncCodeMemPool()->New(mod, !isAssigned ? OP_icall : OP_icallassigned); + // icallproto (, , ..., ) + IcallNode *iCallStmt = mod.CurFuncCodeMemPool()->New(mod, op); lexer.NextToken(); + if (op == OP_icallproto) { + TyIdx tyIdx(0); + if (!ParseDerivedType(tyIdx)) { + Error("error parsing type in ParseStmtIcall for icallproto at "); + return false; + } + iCallStmt->SetRetTyIdx(tyIdx); + } MapleVector opndsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseExprNaryOperand(opndsVec)) { return false; } iCallStmt->SetNOpnd(opndsVec); iCallStmt->SetNumOpnds(opndsVec.size()); - if (isAssigned) { + if (op == OP_icallassigned) { CallReturnVector retsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseCallReturns(retsVec)) { return false; @@ -950,11 +959,15 @@ bool MIRParser::ParseStmtIcall(StmtNodePtr &stmt, bool isAssigned) { } bool MIRParser::ParseStmtIcall(StmtNodePtr &stmt) { - return ParseStmtIcall(stmt, false); + return ParseStmtIcall(stmt, OP_icall); } bool MIRParser::ParseStmtIcallassigned(StmtNodePtr &stmt) { - return ParseStmtIcall(stmt, true); + return ParseStmtIcall(stmt, OP_icallassigned); +} + +bool MIRParser::ParseStmtIcallproto(StmtNodePtr &stmt) { + return ParseStmtIcall(stmt, OP_icallproto); } bool MIRParser::ParseStmtIntrinsiccall(StmtNodePtr &stmt, bool isAssigned) { @@ -3395,6 +3408,7 @@ std::map MIRParser::InitFuncPtrMapForPar funcPtrMap[TK_interfacecallinstantassigned] = &MIRParser::ParseStmtCall; funcPtrMap[TK_icall] = &MIRParser::ParseStmtIcall; funcPtrMap[TK_icallassigned] = &MIRParser::ParseStmtIcallassigned; + funcPtrMap[TK_icallproto] = &MIRParser::ParseStmtIcallproto; funcPtrMap[TK_intrinsiccall] = &MIRParser::ParseStmtIntrinsiccall; funcPtrMap[TK_intrinsiccallassigned] = &MIRParser::ParseStmtIntrinsiccallassigned; funcPtrMap[TK_xintrinsiccall] = &MIRParser::ParseStmtIntrinsiccall; diff --git a/src/mapleall/maple_me/include/lmbc_lower.h b/src/mapleall/maple_me/include/lmbc_lower.h index 81089fb77f..9d74aaa3d0 100644 --- a/src/mapleall/maple_me/include/lmbc_lower.h +++ b/src/mapleall/maple_me/include/lmbc_lower.h @@ -39,6 +39,7 @@ class LMBCLowerer { void LowerIassign(IassignNode *, BlockNode *); void LowerAggIassign(IassignNode *, MIRType *type, int32 offset, BlockNode *); void LowerReturn(NaryStmtNode *retNode, BlockNode *newblk); + MIRFuncType *FuncTypeFromFuncPtrExpr(BaseNode *x); void LowerCall(NaryStmtNode *callNode, BlockNode *newblk); BlockNode *LowerBlock(BlockNode *); void LoadFormalsAssignedToPregs(); diff --git a/src/mapleall/maple_me/src/lmbc_lower.cpp b/src/mapleall/maple_me/src/lmbc_lower.cpp index f9f4beced4..dad5d4e39a 100644 --- a/src/mapleall/maple_me/src/lmbc_lower.cpp +++ b/src/mapleall/maple_me/src/lmbc_lower.cpp @@ -340,6 +340,78 @@ void LMBCLowerer::LowerReturn(NaryStmtNode *retNode, BlockNode *newblk) { newblk->AddStatement(retNode); } +MIRFuncType *LMBCLowerer::FuncTypeFromFuncPtrExpr(BaseNode *x) { + MIRFuncType *res = nullptr; + switch (x->GetOpCode()) { + case OP_regread: { + RegreadNode *regread = static_cast(x); + // must be a formal promoted to preg + for (FormalDef &formalDef : func->GetFormalDefVec()) { + if (!formalDef.formalSym->IsPreg()) { + continue; + } + if (formalDef.formalSym->GetPreg() == func->GetPregTab()->PregFromPregIdx(regread->GetRegIdx())) { + MIRType *mirType = formalDef.formalSym->GetType(); + if (mirType->GetKind() == kTypePointer) { + res = dynamic_cast(static_cast(mirType)->GetPointedType()); + } else { + res = dynamic_cast(mirType); + } + break; + } + } + break; + } + case OP_dread: { + DreadNode *dread = static_cast(x); + MIRSymbol *symbol = func->GetLocalOrGlobalSymbol(dread->GetStIdx()); + MIRType *mirType = symbol->GetType(); + if (dread->GetFieldID() != 0) { + MIRStructType *structty = dynamic_cast(mirType); + CHECK_FATAL(structty, "LMBCLowerer::FuncTypeFromFuncPtrExpr: non-zero fieldID for non-structure"); + FieldPair thepair = structty->TraverseToField(dread->GetFieldID()); + mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(thepair.second.first); + } + if (mirType->GetKind() == kTypePointer) { + res = dynamic_cast(static_cast(mirType)->GetPointedType()); + } else { + res = dynamic_cast(mirType); + } + break; + } + case OP_iread: { + IreadNode *iread = static_cast(x); + MIRPtrType *ptrType = dynamic_cast(iread->GetType()); + MIRType *mirType = ptrType->GetPointedType(); + if (iread->GetFieldID() != 0) { + MIRStructType *structty = dynamic_cast(mirType); + CHECK_FATAL(structty, "LMBCLowerer::FuncTypeFromFuncPtrExpr: non-zero fieldID for non-structure"); + FieldPair thepair = structty->TraverseToField(iread->GetFieldID()); + mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(thepair.second.first); + } + if (mirType->GetKind() == kTypePointer) { + res = dynamic_cast(static_cast(mirType)->GetPointedType()); + } else { + res = dynamic_cast(mirType); + } + break; + } + case OP_addroffunc: { + AddroffuncNode *addrofFunc = static_cast(x); + PUIdx puIdx = addrofFunc->GetPUIdx(); + MIRFunction *f = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx); + res = f->GetMIRFuncType(); + break; + } + case OP_retype: { + res = FuncTypeFromFuncPtrExpr(x->Opnd(0)); + break; + } + default: CHECK_FATAL(false, "LMBCLowerer::FuncTypeFromFuncPtrExpr: NYI"); + } + return res; +} + void LMBCLowerer::LowerCall(NaryStmtNode *naryStmt, BlockNode *newblk) { // go through each parameter uint32 i = 0; @@ -406,7 +478,12 @@ void LMBCLowerer::LowerCall(NaryStmtNode *naryStmt, BlockNode *newblk) { if (naryStmt->GetOpCode() == OP_icall || naryStmt->GetOpCode() == OP_icallassigned) { opnd0 = naryStmt->Opnd(0); naryStmt->GetNopnd().clear(); // remove the call operands - naryStmt->GetNopnd().push_back(opnd0); + // convert to OP_icallproto by finding the function prototype and record in stmt + naryStmt->SetOpCode(OP_icallproto); + MIRFuncType *funcType = FuncTypeFromFuncPtrExpr(opnd0); + static_cast(naryStmt)->SetRetTyIdx(funcType->GetTypeIndex()); + // add back the function pointer operand + naryStmt->GetNopnd().push_back(LowerExpr(opnd0)); naryStmt->SetNumOpnds(1); } else { naryStmt->GetNopnd().clear(); // remove the call operands -- Gitee From f96842a1f65b1189ce03c6559e13a5fa476bcd4a Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Sat, 23 Apr 2022 17:13:09 -0700 Subject: [PATCH 3/4] Fixed some issues found in testing lowering of icall to icallproto --- src/mapleall/maple_be/src/be/lower.cpp | 4 ++- src/mapleall/maple_me/src/lmbc_lower.cpp | 42 +++++++++++++++++++----- src/mapleall/maple_me/src/prop.cpp | 6 ++++ src/mapleall/maple_me/src/ssa_epre.cpp | 3 +- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/mapleall/maple_be/src/be/lower.cpp b/src/mapleall/maple_be/src/be/lower.cpp index c6751c29d1..accad89d39 100644 --- a/src/mapleall/maple_be/src/be/lower.cpp +++ b/src/mapleall/maple_be/src/be/lower.cpp @@ -2525,8 +2525,10 @@ BaseNode *CGLowerer::LowerExpr(BaseNode &parent, BaseNode &expr, BlockNode &blkN case OP_select: if (IsComplexSelect(static_cast(expr))) { return LowerComplexSelect(static_cast(expr), parent, blkNode); - } else { + } else if (mirModule.GetFlavor() != kFlavorLmbc) { return SplitTernaryNodeResult(static_cast(expr), parent, blkNode); + } else { + return &expr; } case OP_sizeoftype: { diff --git a/src/mapleall/maple_me/src/lmbc_lower.cpp b/src/mapleall/maple_me/src/lmbc_lower.cpp index dad5d4e39a..15d617c029 100644 --- a/src/mapleall/maple_me/src/lmbc_lower.cpp +++ b/src/mapleall/maple_me/src/lmbc_lower.cpp @@ -345,12 +345,26 @@ MIRFuncType *LMBCLowerer::FuncTypeFromFuncPtrExpr(BaseNode *x) { switch (x->GetOpCode()) { case OP_regread: { RegreadNode *regread = static_cast(x); - // must be a formal promoted to preg + MIRPreg *preg = func->GetPregTab()->PregFromPregIdx(regread->GetRegIdx()); + // see if it is promoted from a symbol + if (preg->GetOp() == OP_dread) { + const MIRSymbol *symbol = preg->rematInfo.sym; + MIRType *mirType = symbol->GetType(); + if (mirType->GetKind() == kTypePointer) { + res = dynamic_cast(static_cast(mirType)->GetPointedType()); + } else { + res = dynamic_cast(mirType); + } + if (res != nullptr) { + break; + } + } + // check if a formal promoted to preg for (FormalDef &formalDef : func->GetFormalDefVec()) { if (!formalDef.formalSym->IsPreg()) { continue; } - if (formalDef.formalSym->GetPreg() == func->GetPregTab()->PregFromPregIdx(regread->GetRegIdx())) { + if (formalDef.formalSym->GetPreg() == preg) { MIRType *mirType = formalDef.formalSym->GetType(); if (mirType->GetKind() == kTypePointer) { res = dynamic_cast(static_cast(mirType)->GetPointedType()); @@ -383,12 +397,6 @@ MIRFuncType *LMBCLowerer::FuncTypeFromFuncPtrExpr(BaseNode *x) { IreadNode *iread = static_cast(x); MIRPtrType *ptrType = dynamic_cast(iread->GetType()); MIRType *mirType = ptrType->GetPointedType(); - if (iread->GetFieldID() != 0) { - MIRStructType *structty = dynamic_cast(mirType); - CHECK_FATAL(structty, "LMBCLowerer::FuncTypeFromFuncPtrExpr: non-zero fieldID for non-structure"); - FieldPair thepair = structty->TraverseToField(iread->GetFieldID()); - mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(thepair.second.first); - } if (mirType->GetKind() == kTypePointer) { res = dynamic_cast(static_cast(mirType)->GetPointedType()); } else { @@ -404,7 +412,22 @@ MIRFuncType *LMBCLowerer::FuncTypeFromFuncPtrExpr(BaseNode *x) { break; } case OP_retype: { - res = FuncTypeFromFuncPtrExpr(x->Opnd(0)); + MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast(x)->GetTyIdx()); + if (mirType->GetKind() == kTypePointer) { + res = dynamic_cast(static_cast(mirType)->GetPointedType()); + } else { + res = dynamic_cast(mirType); + } + if (res == nullptr) { + res = FuncTypeFromFuncPtrExpr(x->Opnd(0)); + } + break; + } + case OP_select: { + res = FuncTypeFromFuncPtrExpr(x->Opnd(1)); + if (res == nullptr) { + res = FuncTypeFromFuncPtrExpr(x->Opnd(2)); + } break; } default: CHECK_FATAL(false, "LMBCLowerer::FuncTypeFromFuncPtrExpr: NYI"); @@ -481,6 +504,7 @@ void LMBCLowerer::LowerCall(NaryStmtNode *naryStmt, BlockNode *newblk) { // convert to OP_icallproto by finding the function prototype and record in stmt naryStmt->SetOpCode(OP_icallproto); MIRFuncType *funcType = FuncTypeFromFuncPtrExpr(opnd0); + CHECK_FATAL(funcType != nullptr, "LMBCLowerer::LowerCall: cannot find prototype for icall"); static_cast(naryStmt)->SetRetTyIdx(funcType->GetTypeIndex()); // add back the function pointer operand naryStmt->GetNopnd().push_back(LowerExpr(opnd0)); diff --git a/src/mapleall/maple_me/src/prop.cpp b/src/mapleall/maple_me/src/prop.cpp index 08a15edc27..fea78bcba1 100644 --- a/src/mapleall/maple_me/src/prop.cpp +++ b/src/mapleall/maple_me/src/prop.cpp @@ -647,6 +647,12 @@ MeExpr &Prop::PropVar(VarMeExpr &varMeExpr, bool atParm, bool checkPhi) { propsPerformed >= propLimit) { return varMeExpr; } + if (st->GetType() && st->GetType()->GetKind() == kTypePointer) { + MIRPtrType *ptrType = static_cast(st->GetType()); + if (ptrType->GetPointedType()->GetKind() == kTypeFunction) { + return varMeExpr; + } + } if (varMeExpr.GetDefBy() == kDefByStmt) { DassignMeStmt *defStmt = static_cast(varMeExpr.GetDefStmt()); diff --git a/src/mapleall/maple_me/src/ssa_epre.cpp b/src/mapleall/maple_me/src/ssa_epre.cpp index 34e1f1812a..9ddf02c99a 100644 --- a/src/mapleall/maple_me/src/ssa_epre.cpp +++ b/src/mapleall/maple_me/src/ssa_epre.cpp @@ -368,7 +368,8 @@ void SSAEPre::BuildWorkListExpr(MeStmt &meStmt, int32 seqStmt, MeExpr &meExpr, b if (!epreIncludeRef && meOpExpr->GetPrimType() == PTY_ref) { break; } - if (meOpExpr->GetOp() == OP_gcmallocjarray || meOpExpr->GetOp() == OP_gcmalloc) { + if (meOpExpr->GetOp() == OP_gcmallocjarray || meOpExpr->GetOp() == OP_gcmalloc || + meOpExpr->GetOp() == OP_retype) { break; } if (isRebuild && !hasTempVarAs1Opnd) { -- Gitee From 26536879432328d4d6836f2ec03e92ea4a13184c Mon Sep 17 00:00:00 2001 From: William Chen Date: Wed, 27 Apr 2022 11:53:47 -0700 Subject: [PATCH 4/4] Be conservative with size of stack. Use RFP for prolog under lmbc. --- .../maple_be/include/cg/aarch64/aarch64_proepilog.h | 6 +++++- src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h index 1d35f1f69a..cd24e2bafa 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h @@ -29,7 +29,11 @@ class AArch64GenProEpilog : public GenProEpilog { public: explicit AArch64GenProEpilog(CGFunc &func) : GenProEpilog(func) { useFP = func.UseFP(); - stackBaseReg = useFP ? R29 : RSP; + if (func.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + stackBaseReg = RFP; + } else { + stackBaseReg = useFP ? R29 : RSP; + } exitBB2CallSitesMap.clear(); } ~AArch64GenProEpilog() override = default; diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp index 9572204d34..514b2fcf61 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp @@ -285,7 +285,7 @@ void AArch64MemLayout::LayoutFormalParams() { void AArch64MemLayout::LayoutLocalVariables(std::vector &tempVar, std::vector &returnDelays) { if (be.GetMIRModule().GetFlavor() == kFlavorLmbc && mirFunction->GetFormalCount() == 0) { - segLocals.SetSize(mirFunction->GetFrameSize() - mirFunction->GetOutParmSize()); + segLocals.SetSize(mirFunction->GetFrameSize()/* - mirFunction->GetOutParmSize()*/); return; } -- Gitee