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 4472e24382526658f2a47fd23ced4218559ca3e3..28066b6c3738c9124ed6bafe33069f7b6f65e204 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -124,7 +124,9 @@ 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 LmbcSelectParmList(ListOperand *srcOpnds, bool isArgReturn); + bool LmbcSmallAggForRet(BlkassignoffNode &bNode, Operand *src); + bool LmbcSmallAggForCall(BlkassignoffNode &bNode, Operand *src); void SelectAggDassign(DassignNode &stmt) override; void SelectIassign(IassignNode &stmt) override; void SelectIassignoff(IassignoffNode &stmt) override; @@ -479,7 +481,7 @@ class AArch64CGFunc : public CGFunc { void GenerateCleanupCode(BB &bb) override; bool NeedCleanup() override; void GenerateCleanupCodeForExtEpilog(BB &bb) override; - uint32 FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) 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); diff --git a/src/mapleall/maple_be/include/cg/call_conv.h b/src/mapleall/maple_be/include/cg/call_conv.h index c532e1a7d64349450322d2f0b572606f17ce734c..ba8e2fdc318cd48fc35c0419077d2dfa4764c6c7 100644 --- a/src/mapleall/maple_be/include/cg/call_conv.h +++ b/src/mapleall/maple_be/include/cg/call_conv.h @@ -62,10 +62,17 @@ struct CCLocInfo { class LmbcFormalParamInfo { public: - LmbcFormalParamInfo(PrimType pType, uint32 ofst, uint32 sz) : primType(pType), offset(ofst), size(sz) {} + LmbcFormalParamInfo(PrimType pType, uint32 ofst, uint32 sz) : + type(nullptr), primType(pType), offset(ofst), size(sz), regNO(0), vregNO(0), numRegs(0), fpSize(0), isReturn(false), isPureFloat(false), isOnStack(false) {} ~LmbcFormalParamInfo() = default; + MIRStructType *GetType() { + return type; + } + void SetType(MIRStructType *ty) { + type = ty; + } PrimType GetPrimType() { return primType; } @@ -108,13 +115,29 @@ class LmbcFormalParamInfo { void SetFpSize(uint32 sz) { fpSize = sz; } + bool IsReturn() { + return isReturn; + } + void SetIsReturn() { + isReturn = true; + } bool IsPureFloat() { return isPureFloat; } void SetIsPureFloat() { isPureFloat = true; } + bool IsInReg() { + return (isOnStack == false); + } + bool IsOnStack() { + return isOnStack; + } + void SetIsOnStack() { + isOnStack = true; + } private: + MIRStructType *type; PrimType primType; uint32 offset; uint32 size; /* size primtype or struct */ @@ -122,7 +145,9 @@ class LmbcFormalParamInfo { regno_t vregNO = 0; /* if no explicit regassing from IR, create move from param reg */ uint32 numRegs = 0; /* number of regs for struct param */ uint32 fpSize = 0; /* size of fp param if isPureFloat */ + bool isReturn; bool isPureFloat = false; + bool isOnStack; /* small struct with arrays need to be saved onto stack */ }; } /* namespace maplebe */ diff --git a/src/mapleall/maple_be/include/cg/cgfunc.h b/src/mapleall/maple_be/include/cg/cgfunc.h index 0391e44a5bd5d57eb489fe80bfa13abc530fb987..f99eafc57b0f1b3db10c1681582642d4dcbb2720 100644 --- a/src/mapleall/maple_be/include/cg/cgfunc.h +++ b/src/mapleall/maple_be/include/cg/cgfunc.h @@ -149,7 +149,7 @@ class CGFunc { virtual void GenerateCleanupCodeForExtEpilog(BB &bb) = 0; void CreateLmbcFormalParamInfo(); - virtual uint32 FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) = 0; + virtual uint32 FloatParamRegRequired(MIRStructType *structType, uint32 &fpSize) = 0; virtual void AssignLmbcFormalParams() = 0; LmbcFormalParamInfo *GetLmbcFormalParamInfo(uint32 offset); void GenerateLoc(StmtNode *stmt, unsigned &lastSrcLoc, unsigned &lastMplLoc); 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 46e0ae1922f62c122e276ac8a05b61a97c515a63..0e972a4bf734bea8abb82d0ef383e54ce9afb970 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp @@ -38,8 +38,8 @@ void AArch64MoveRegArgs::CollectRegisterArgs(std::map &argsL uint32 start = 0; if (numFormal) { MIRFunction *func = const_cast(aarchCGFunc->GetBecommon().GetMIRModule().CurFunction()); - if (aarchCGFunc->GetBecommon().HasFuncReturnType(*func)) { - TyIdx tyIdx = aarchCGFunc->GetBecommon().GetFuncReturnType(*func); + if (func->IsReturnStruct()) { + TyIdx tyIdx = func->GetFuncRetStructTyIdx(); if (aarchCGFunc->GetBecommon().GetTypeSize(tyIdx) <= k16ByteSize) { start = 1; } @@ -436,9 +436,9 @@ void AArch64MoveRegArgs::MoveVRegisterArgs() { uint32 start = 0; if (formalCount) { MIRFunction *func = const_cast(aarchCGFunc->GetBecommon().GetMIRModule().CurFunction()); - if (aarchCGFunc->GetBecommon().HasFuncReturnType(*func)) { - TyIdx idx = aarchCGFunc->GetBecommon().GetFuncReturnType(*func); - if (aarchCGFunc->GetBecommon().GetTypeSize(idx) <= k16BitSize) { + if (func->IsReturnStruct()) { + TyIdx tyIdx = func->GetFuncRetStructTyIdx(); + if (aarchCGFunc->GetBecommon().GetTypeSize(tyIdx) <= k16BitSize) { start = 1; } } 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 9373c19f6ba8050c1c3d77363220ad0019a28c3d..0be11cdb40dfb6cc1b6e063f216d3506b2bff5c8 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 @@ -303,8 +303,9 @@ int32 AArch64CallConvImpl::LocateNextParm(MIRType &mirType, CCLocInfo &pLoc, boo if (isFirst) { MIRFunction *func = tFunc != nullptr ? tFunc : const_cast(beCommon.GetMIRModule().CurFunction()); - if (beCommon.HasFuncReturnType(*func)) { - size_t size = beCommon.GetTypeSize(beCommon.GetFuncReturnType(*func)); + if (func->IsReturnStruct()) { + TyIdx tyIdx = func->GetFuncRetStructTyIdx(); + size_t size = beCommon.GetTypeSize(tyIdx); if (size == 0) { /* For return struct size 0 there is no return value. */ return 0; @@ -667,7 +668,7 @@ void AArch64CallConvImpl::InitReturnInfo(MIRType &retTy, CCLocInfo &ccLocInfo) { ccLocInfo.primTypeOfReg0 = PTY_i64; } } else { - ASSERT(ccLocInfo.regCount == kMaxRegCount, "reg count from ClassifyAggregate() should be 0, 1, or 2"); + ASSERT(ccLocInfo.regCount <= k2ByteSize, "reg count from ClassifyAggregate() should be 0, 1, or 2"); ASSERT(classes[0] == kAArch64IntegerClass, "error val :classes[0]"); ASSERT(classes[1] == kAArch64IntegerClass, "error val :classes[1]"); ccLocInfo.reg0 = AArch64Abi::intReturnRegs[0]; 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 095fe4ee9388028f046bacc6ce15d85ab64b2dbe..cd6f49866a7309df9ae4eec006cbad51a8fe8fe1 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -1926,11 +1926,22 @@ void AArch64CGFunc::SelectIassignfpoff(IassignFPoffNode &stmt, Operand &opnd) { uint32 bitlen = GetPrimTypeSize(primType) * kBitsPerByte; Operand &srcOpnd = LoadIntoRegister(opnd, primType); + MemOperand *memOpnd; RegOperand *rfp = &GetOrCreatePhysicalRegisterOperand(RFP, k64BitSize, kRegTyInt); - OfstOperand *offsetOpnd = &CreateOfstOpnd(offset, k32BitSize); - MemOperand &memOpnd = GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, rfp, nullptr, offsetOpnd, nullptr); + if (offset < 0) { + RegOperand *baseOpnd = &CreateRegisterOperandOfType(PTY_a64); + ImmOperand &immOpnd = CreateImmOperand(offset, k32BitSize, true); + Insn &addInsn = GetCG()->BuildInstruction(MOP_xaddrri12, *baseOpnd, *rfp, immOpnd); + GetCurBB()->AppendInsn(addInsn); + OfstOperand *offsetOpnd = &CreateOfstOpnd(0, k32BitSize); + memOpnd = &GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, baseOpnd, nullptr, offsetOpnd, nullptr); + } else { + OfstOperand *offsetOpnd = &CreateOfstOpnd(offset, k32BitSize); + memOpnd = &GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, rfp, nullptr, offsetOpnd, nullptr); + } + memOpnd->SetStackMem(true); MOperator mOp = PickStInsn(bitlen, primType); - Insn &store = GetCG()->BuildInstruction(mOp, srcOpnd, memOpnd); + Insn &store = GetCG()->BuildInstruction(mOp, srcOpnd, *memOpnd); GetCurBB()->AppendInsn(store); } @@ -1958,7 +1969,7 @@ void AArch64CGFunc::SelectIassignspoff(PrimType pTy, int32 offset, Operand &opnd IncLmbcTotalArgs(); /* num of args */ } -/* Search for CALL/ICALL node, must be called from a blkassignoff node */ +/* Search for CALL/ICALL/ICALLPROTO 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) { @@ -1972,52 +1983,100 @@ MIRType *AArch64CGFunc::GetAggTyFromCallSite(StmtNode *stmt) { if (stmt->GetOpCode() == OP_call) { CallNode *callNode = static_cast(stmt); MIRFunction *fn = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(callNode->GetPUIdx()); + if (fn->IsReturnStruct()) { + ++nargs; + } 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()); + // would return null if the actual parameter is bogus + } else if (stmt->GetOpCode() == OP_icallproto) { + IcallNode *icallproto = static_cast(stmt); + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(icallproto->GetRetTyIdx()); MIRFuncType *fType = static_cast(type); + MIRType *retType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fType->GetRetTyIdx()); + if (retType->GetKind() == kTypeStruct) { + ++nargs; + } ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fType->GetNthParamType(nargs)); + } else { + CHECK_FATAL(stmt->GetOpCode() == OP_icallproto, "GetAggTyFromCallSite:: unexpected call operator"); } - 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; +/* return true if blkassignoff for return, false otherwise */ +bool AArch64CGFunc::LmbcSmallAggForRet(BlkassignoffNode &bNode, Operand *src) { + PrimType pTy; + uint32 size = 0; + AArch64reg regno = static_cast(static_cast(src)->GetRegisterNumber()); + MIRFunction *func = &GetFunction(); + + if (func->IsReturnStruct()) { + /* This blkassignoff is for struct return? */ + int32 loadSize; + int32 numRegs = 0; + if (bNode.GetNext()->GetOpCode() == OP_return) { + MIRStructType *ty = static_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(func->GetFuncRetStructTyIdx())); + uint32 fpregs = FloatParamRegRequired(ty, size); + if (fpregs > 0) { + /* pure floating point in agg */ + numRegs = fpregs; + pTy = (size == k4ByteSize) ? PTY_f32 : PTY_f64; + loadSize = GetPrimTypeSize(pTy) * kBitsPerByte; + for (uint32 i = 0; i < fpregs; i++) { + int s = (i == 0) ? 0 : (i * size); + MemOperand &mem = CreateMemOpnd(regno, s, size * kBitsPerByte); + AArch64reg reg = static_cast(V0 + i); + RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, loadSize, kRegTyFloat); + SelectCopy(*res, pTy, mem, pTy); + } + } else { + /* int/float mixed */ + numRegs = 2; + pTy = PTY_i64; + size = k4ByteSize; + switch (bNode.blockSize) { + case 1: pTy = PTY_i8; + break; + case 2: pTy = PTY_i16; + break; + case 4: pTy = PTY_i32; + break; + default: size = k8ByteSize; /* pTy remains i64 */ + } + loadSize = GetPrimTypeSize(pTy) * kBitsPerByte; + MemOperand &mem = CreateMemOpnd(regno, 0, size * kBitsPerByte); + RegOperand *res = &GetOrCreatePhysicalRegisterOperand(R0, loadSize, kRegTyInt); + SelectCopy(*res, pTy, mem, pTy); + if (bNode.blockSize > k8ByteSize) { + MemOperand &mem = CreateMemOpnd(regno, k8ByteSize, size * kBitsPerByte); + res = &GetOrCreatePhysicalRegisterOperand(R1, loadSize, kRegTyInt); + SelectCopy(*res, pTy, mem, pTy); + } + } + bool intReg = fpregs == 0; + for (uint32 i = 0; i < numRegs; i++) { + AArch64reg preg = static_cast((intReg ? R0 : V0) + i); + MOperator mop = intReg ? MOP_pseudo_ret_int: MOP_pseudo_ret_float; + RegOperand &dest = GetOrCreatePhysicalRegisterOperand(preg, loadSize, intReg ? kRegTyInt : kRegTyFloat); + Insn &pseudo = GetCG()->BuildInstruction(mop, dest); + GetCurBB()->AppendInsn(pseudo); + } + return true; } } + return false; +} - Operand *dest = HandleExpr(bNode, *bNode.Opnd(0)); +/* return true if blkassignoff for return, false otherwise */ +bool AArch64CGFunc::LmbcSmallAggForCall(BlkassignoffNode &bNode, Operand *src) { + AArch64reg regno = static_cast(static_cast(src)->GetRegisterNumber()); if (IsBlkassignForPush(bNode)) { - /* follow calling convention */ - AArch64reg regno = static_cast(static_cast(src)->GetRegisterNumber()); + PrimType pTy = PTY_i64; MIRStructType *ty = static_cast(GetAggTyFromCallSite(&bNode)); - uint32 fpregs = FloatParamRegRequired(*ty, size); + uint32 size = 0; + uint32 fpregs = ty ? FloatParamRegRequired(ty, size) : 0; /* fp size determined */ if (fpregs > 0) { /* pure floating point in agg */ pTy = (size == k4ByteSize) ? PTY_f32 : PTY_f64; @@ -2026,30 +2085,61 @@ void AArch64CGFunc::SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) 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); + SetLmbcArgInfo(res, pTy, bNode.offset + s, fpregs); IncLmbcArgsInRegs(kRegTyFloat); } IncLmbcTotalArgs(); - return; + return true; } else if (bNode.blockSize <= k16ByteSize) { - /* integer/mixed types */ + /* integer/mixed types in register/s */ + size = k4ByteSize; + switch (bNode.blockSize) { + case 1: pTy = PTY_i8; + break; + case 2: pTy = PTY_i16; + break; + case 4: pTy = PTY_i32; + break; + default: size = k8ByteSize; /* pTy remains i64 */ + } MemOperand &mem = CreateMemOpnd(regno, 0, size * kBitsPerByte); RegOperand *res = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, size)); SelectCopy(*res, pTy, mem, pTy); - SetLmbcArgInfo(res, pTy, bNode.offset, 2); + SetLmbcArgInfo(res, pTy, bNode.offset, bNode.blockSize > k8ByteSize ? 2 : 1); 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); + SetLmbcArgInfo(res, pTy, bNode.offset + k8ByteSize, 2); IncLmbcArgsInRegs(kRegTyInt); } IncLmbcTotalArgs(); - return; + return true; } } - /* pass on stack */ + return false; +} + +/* If blkassignoff 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) +{ + CHECK_FATAL(src->GetKind() == Operand::kOpdRegister, "blkassign src type not in register"); + if (GetLmbcArgInfo() == nullptr) { + LmbcArgInfo *p = memPool->New(*GetFuncScopeAllocator()); + SetLmbcArgInfo(p); + } + if (LmbcSmallAggForRet(bNode, src)) { + return; + } else if (LmbcSmallAggForCall(bNode, src)) { + return; + } + /* memcpy for agg assign OR large agg for arg/ret */ + Operand *dest = HandleExpr(bNode, *bNode.Opnd(0)); RegOperand *regResult = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); std::vector opndVec; opndVec.push_back(regResult); /* result */ @@ -2058,7 +2148,7 @@ void AArch64CGFunc::SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) 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); + SetLmbcArgInfo(static_cast(src), PTY_i64, (int32)bNode.offset, 1); IncLmbcArgsInRegs(kRegTyInt); IncLmbcTotalArgs(); } @@ -2813,13 +2903,24 @@ Operand *AArch64CGFunc::SelectIreadoff(const BaseNode &parent, IreadoffNode &ire } RegOperand *AArch64CGFunc::GenLmbcParamLoad(int32 offset, uint32 byteSize, RegType regType, PrimType primType) { + MemOperand *memOpnd; 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); + if (offset < 0) { + RegOperand *baseOpnd = &CreateRegisterOperandOfType(PTY_a64); + ImmOperand &immOpnd = CreateImmOperand(offset, k32BitSize, true); + Insn &addInsn = GetCG()->BuildInstruction(MOP_xaddrri12, *baseOpnd, *rfp, immOpnd); + GetCurBB()->AppendInsn(addInsn); + OfstOperand *offsetOpnd = &CreateOfstOpnd(0, k32BitSize); + memOpnd = &GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, baseOpnd, nullptr, offsetOpnd, nullptr); + } else { + OfstOperand *offsetOpnd = &CreateOfstOpnd(offset, k32BitSize); + memOpnd = &GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, bitlen, rfp, nullptr, offsetOpnd, nullptr); + } + memOpnd->SetStackMem(true); RegOperand *result = &GetOrCreateVirtualRegisterOperand(NewVReg(regType, byteSize)); MOperator mOp = PickLdInsn(bitlen, primType); - Insn &load = GetCG()->BuildInstruction(mOp, *result, memOpnd); + Insn &load = GetCG()->BuildInstruction(mOp, *result, *memOpnd); GetCurBB()->AppendInsn(load); return result; } @@ -2834,6 +2935,8 @@ Operand *AArch64CGFunc::SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode if (offset >= 0) { LmbcFormalParamInfo *info = GetLmbcFormalParamInfo(offset); if (info->GetPrimType() == PTY_agg) { + result = GenLmbcParamLoad(offset, bytelen, regty, primType); +#if 0 bool inVreg = (info->GetVregNO() > 0); regno_t reg = inVreg ? info->GetVregNO() : info->GetRegNO(); if (info->IsPureFloat()) { @@ -2848,7 +2951,7 @@ Operand *AArch64CGFunc::SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode } else { if (reg == 0) { result = GenLmbcParamLoad(offset, bytelen, regty, primType); - } else { + } else if (info->IsInReg()) { if (info->GetSize() > k16ByteSize) { result = GenLmbcParamLoad(offset, bytelen, regty, primType); } else if (bytelen == k8ByteSize) { @@ -2884,8 +2987,11 @@ Operand *AArch64CGFunc::SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode result = extractReg; } } + } else { + result = GenLmbcParamLoad(offset, bytelen, regty, primType); } } +#endif } else { CHECK_FATAL(primType == info->GetPrimType(), "Incorrect primtype"); CHECK_FATAL(offset == info->GetOffset(), "Incorrect offset"); @@ -6114,9 +6220,9 @@ void AArch64CGFunc::GenerateCleanupCode(BB &bb) { SetCleanupBB(*GetCurBB()); } -uint32 AArch64CGFunc::FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize) { +uint32 AArch64CGFunc::FloatParamRegRequired(MIRStructType *structType, uint32 &fpSize) { AArch64CallConvImpl parmlocator(GetBecommon()); - return parmlocator.FloatParamRegRequired(structType, fpSize); + return parmlocator.FloatParamRegRequired(*structType, fpSize); } /* @@ -6131,7 +6237,9 @@ void AArch64CGFunc::AssignLmbcFormalParams() { for (auto param : GetLmbcParamVec()) { primType = param->GetPrimType(); offset = param->GetOffset(); - if (IsPrimitiveInteger(primType)) { + if (param->IsReturn()) { + param->SetRegNO(R8); + } else if (IsPrimitiveInteger(primType)) { if (intReg > R7) { param->SetRegNO(0); } else { @@ -6152,6 +6260,7 @@ void AArch64CGFunc::AssignLmbcFormalParams() { param->SetRegNO(0); } else { param->SetRegNO(fpReg); + param->SetNumRegs(numFpRegs); fpReg += numFpRegs; } } else if (param->GetSize() > k16ByteSize) { @@ -6159,6 +6268,7 @@ void AArch64CGFunc::AssignLmbcFormalParams() { param->SetRegNO(0); } else { param->SetRegNO(intReg); + param->SetIsOnStack(); intReg++; } } else if (param->GetSize() <= k8ByteSize) { @@ -6166,6 +6276,7 @@ void AArch64CGFunc::AssignLmbcFormalParams() { param->SetRegNO(0); } else { param->SetRegNO(intReg); + param->SetNumRegs(kOneRegister); intReg++; } } else { @@ -6200,6 +6311,9 @@ void AArch64CGFunc::AssignLmbcFormalParams() { if (param->GetVregNO() == 0) { param->SetVregNO(vreg); } + Operand *memOpd = &CreateMemOpnd(RFP, offset + (i * rSize), rSize); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(PickStInsn(rSize * kBitsPerByte, pType), dest, *memOpd)); + param->SetIsOnStack(); } } } else { @@ -7491,8 +7605,9 @@ size_t AArch64CGFunc::SelectParmListGetStructReturnSize(StmtNode &naryNode) { MIRFunction *callFunc = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(callNode.GetPUIdx()); TyIdx retIdx = callFunc->GetReturnTyIdx(); size_t retSize = GetBecommon().GetTypeSize(retIdx.GetIdx()); - if ((retSize == 0) && GetBecommon().HasFuncReturnType(*callFunc)) { - return GetBecommon().GetTypeSize(GetBecommon().GetFuncReturnType(*callFunc)); + if ((retSize == 0) && callFunc->IsReturnStruct()) { + TyIdx tyIdx = callFunc->GetFuncRetStructTyIdx(); + return GetBecommon().GetTypeSize(tyIdx); } return retSize; } else if (naryNode.GetOpCode() == OP_icall) { @@ -8051,7 +8166,7 @@ void AArch64CGFunc::IntrinsifyStringIndexOf(ListOperand &srcOpnds, const MIRSymb /* Lmbc calls have no argument, they are all explicit iassignspoff or blkassign. Info collected and to be emitted here */ -void AArch64CGFunc::LmbcSelectParmList(ListOperand *srcOpnds) { +void AArch64CGFunc::LmbcSelectParmList(ListOperand *srcOpnds, bool isArgReturn) { if (GetLmbcArgInfo() == nullptr) { return; /* no arg */ } @@ -8062,16 +8177,17 @@ void AArch64CGFunc::LmbcSelectParmList(ListOperand *srcOpnds) { MapleVector ®s = GetLmbcCallArgNumOfRegs(); int iCnt = 0; int fCnt = 0; - for (int i = 0; i < args.size(); i++) { + for (int i = isArgReturn ? 1 : 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++); - } + AArch64reg reg; + if (args[i]->IsOfIntClass() && (iCnt + regs[i]) <= k8ByteSize) { + reg = static_cast(R0 + iCnt++); + RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(pTy) * kBitsPerByte, ty); + SelectCopy(*res, pTy, *args[i], pTy); + srcOpnds->PushOpnd(*res); + } else if (!args[i]->IsOfIntClass() && (fCnt + regs[i]) <= k8ByteSize) { + reg = static_cast(V0 + fCnt++); RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(pTy) * kBitsPerByte, ty); SelectCopy(*res, pTy, *args[i], pTy); srcOpnds->PushOpnd(*res); @@ -8082,6 +8198,13 @@ void AArch64CGFunc::LmbcSelectParmList(ListOperand *srcOpnds) { GetCG()->BuildInstruction(PickStInsn(pSize * kBitsPerByte, pTy), *args[i], memOpd)); } } + /* Load x8 if 1st arg is for agg return */ + if (isArgReturn) { + AArch64reg reg = static_cast(R8); + RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(PTY_a64) * kBitsPerByte, kRegTyInt); + SelectCopy(*res, PTY_a64, *args[0], PTY_a64); + srcOpnds->PushOpnd(*res); + } ResetLmbcArgInfo(); /* reset */ ResetLmbcArgsInRegs(); ResetLmbcTotalArgs(); @@ -8099,7 +8222,7 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) { ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { - LmbcSelectParmList(srcOpnds); + LmbcSelectParmList(srcOpnds, fn->IsFirstArgReturn()); } bool callNative = false; if ((fsym->GetName() == "MCC_CallFastNative") || (fsym->GetName() == "MCC_CallFastNativeExt") || @@ -8167,7 +8290,11 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) { void AArch64CGFunc::SelectIcall(IcallNode &icallNode, Operand &srcOpnd) { ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { - LmbcSelectParmList(srcOpnds); +#if 0 // TBD + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(icallNode.GetRetTyIdx()); + MIRFuncType *fType = static_cast(type); +#endif + LmbcSelectParmList(srcOpnds, false /*fType->GetRetAttrs().GetAttr(ATTR_firstarg_return)*/); } else { SelectParmList(icallNode, *srcOpnds); } @@ -9055,7 +9182,6 @@ void AArch64CGFunc::SelectAddAfterInsn(Operand &resOpnd, Operand &opnd0, Operand "Spill memory operand should be with a immediate offset."); ImmOperand *immOpnd = static_cast(&opnd1); - ASSERT(!immOpnd->IsNegative(), "Spill offset should be positive number."); MOperator mOpCode = MOP_undef; Insn *curInsn = &insn; @@ -9093,13 +9219,16 @@ void AArch64CGFunc::SelectAddAfterInsn(Operand &resOpnd, Operand &opnd0, Operand } } else { /* load into register */ - RegOperand ®Opnd = CreateRegisterOperandOfType(primType); - SelectCopyImm(regOpnd, *immOpnd, primType); + RegOperand &movOpnd = GetOrCreatePhysicalRegisterOperand(R16, dsize, kRegTyInt); + mOpCode = is64Bits ? MOP_xmovri64 : MOP_xmovri32; + Insn &movInsn = GetCG()->BuildInstruction(mOpCode, movOpnd, *immOpnd); mOpCode = is64Bits ? MOP_xaddrrr : MOP_waddrrr; - Insn &newInsn = GetCG()->BuildInstruction(mOpCode, resOpnd, opnd0, regOpnd); + Insn &newInsn = GetCG()->BuildInstruction(mOpCode, resOpnd, opnd0, movOpnd); if (isDest) { insn.GetBB()->InsertInsnAfter(insn, newInsn); + insn.GetBB()->InsertInsnAfter(insn, movInsn); } else { + insn.GetBB()->InsertInsnBefore(insn, movInsn); insn.GetBB()->InsertInsnBefore(insn, newInsn); } } 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 45561cd73fdace9ff497cd5426255167ed73bd8f..be7c72ae086e7250fcfdf58e2599829e074285d9 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp @@ -133,9 +133,9 @@ void AArch64MemLayout::LayoutVarargParams() { if (be.GetMIRModule().IsCModule() && func->GetAttr(FUNCATTR_varargs)) { for (uint32 i = 0; i < func->GetFormalCount(); i++) { if (i == 0) { - if (be.HasFuncReturnType(*func)) { - TyIdx tidx = be.GetFuncReturnType(*func); - if (be.GetTypeSize(tidx.GetIdx()) <= k16ByteSize) { + if (func->IsReturnStruct()) { + TyIdx tyIdx = func->GetFuncRetStructTyIdx(); + if (be.GetTypeSize(tyIdx.GetIdx()) <= k16ByteSize) { continue; } } @@ -189,13 +189,15 @@ void AArch64MemLayout::LayoutVarargParams() { } void AArch64MemLayout::LayoutFormalParams() { - if (be.GetMIRModule().GetFlavor() == kFlavorLmbc && mirFunction->GetFormalCount() == 0) { + bool isLmbc = (be.GetMIRModule().GetFlavor() == kFlavorLmbc); + if (isLmbc && 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()); + segArgsRegPassed.SetSize(mirFunction->GetOutParmSize() + kTwoRegister * k8ByteSize); return; } @@ -207,11 +209,11 @@ void AArch64MemLayout::LayoutFormalParams() { AArch64SymbolAlloc *symLoc = memAllocator->GetMemPool()->New(); SetSymAllocInfo(stIndex, *symLoc); if (i == 0) { - if (be.HasFuncReturnType(*mirFunction)) { + if (mirFunction->IsReturnStruct()) { symLoc->SetMemSegment(GetSegArgsRegPassed()); symLoc->SetOffset(GetSegArgsRegPassed().GetSize()); - TyIdx tidx = be.GetFuncReturnType(*mirFunction); - if (be.GetTypeSize(tidx.GetIdx()) > k16ByteSize) { + TyIdx tyIdx = mirFunction->GetFuncRetStructTyIdx(); + if (be.GetTypeSize(tyIdx.GetIdx()) > k16ByteSize) { if (CGOptions::IsArm64ilp32()) { segArgsRegPassed.SetSize(segArgsRegPassed.GetSize() + k8ByteSize); } else { @@ -253,6 +255,8 @@ void AArch64MemLayout::LayoutFormalParams() { segArgsRegPassed.SetSize(static_cast(RoundUp(segArgsRegPassed.GetSize(), align))); symLoc->SetOffset(segArgsRegPassed.GetSize()); segArgsRegPassed.SetSize(segArgsRegPassed.GetSize() + size); + } else if (isLmbc) { + segArgsRegPassed.SetSize(segArgsRegPassed.GetSize() + k8ByteSize); } noStackPara = true; } else { /* stack */ @@ -285,7 +289,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()); + segLocals.SetSize(mirFunction->GetFrameSize() - mirFunction->GetOutParmSize()); return; } @@ -368,7 +372,11 @@ void AArch64MemLayout::LayoutReturnRef(std::vector &returnDelays, symLoc->SetOffset(segRefLocals.GetSize()); segRefLocals.SetSize(segRefLocals.GetSize() + be.GetTypeSize(tyIdx)); } - segArgsToStkPass.SetSize(FindLargestActualArea(structCopySize)); + if (be.GetMIRModule().GetFlavor() == kFlavorLmbc) { + segArgsToStkPass.SetSize(mirFunction->GetOutParmSize()); + } else { + segArgsToStkPass.SetSize(FindLargestActualArea(structCopySize)); + } maxParmStackSize = static_cast(segArgsToStkPass.GetSize()); if (Globals::GetInstance()->GetOptimLevel() == 0) { AssignSpillLocationsToPseudoRegisters(); @@ -388,7 +396,7 @@ void AArch64MemLayout::LayoutReturnRef(std::vector &returnDelays, void AArch64MemLayout::LayoutActualParams() { for (size_t i = 0; i < mirFunction->GetFormalCount(); ++i) { if (i == 0) { - if (be.HasFuncReturnType(*mirFunction)) { + if (mirFunction->IsReturnStruct()) { continue; } } 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 9f1ae84cd8ad0b0eefa540dada6808a41a3f20e4..eaa5726d435a939ffd0706b8ec4e0b37ede60e38 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,15 +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; - } + bool isLmbc = (aarchCGFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc); uint32 opndNum = insn.GetOperandSize(); MemLayout *memLayout = aarchCGFunc.GetMemlayout(); bool stackBaseOpnd = false; - AArch64reg stackBaseReg = aarchCGFunc.UseFP() ? R29 : RSP; + AArch64reg stackBaseReg = isLmbc ? R29 : (aarchCGFunc.UseFP() ? R29 : RSP); for (uint32 i = 0; i < opndNum; ++i) { Operand &opnd = insn.GetOperand(i); if (opnd.IsRegister()) { diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_peep.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_peep.cpp index 67b1bd6302643d438dfb4f7d138434dbcf7fb518..b52e2bfb151682d57e429af8e30c75064a4c55ce 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_peep.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_peep.cpp @@ -4761,19 +4761,20 @@ void ComplexMemOperandPreAddAArch64::Run(BB &bb, Insn &insn) { } MemOperand *memOpnd = static_cast(nextInsn->GetMemOpnd()); auto &newBaseOpnd = static_cast(insn.GetOperand(kInsnSecondOpnd)); - auto &newIndexOpnd = static_cast(insn.GetOperand(kInsnThirdOpnd)); if (newBaseOpnd.GetSize() != k64BitSize) { return; } + auto &newIndexOpnd = static_cast(insn.GetOperand(kInsnThirdOpnd)); if (newIndexOpnd.GetSize() <= k32BitSize) { MemOperand &newMemOpnd = aarch64CGFunc->GetOrCreateMemOpnd(MemOperand::kAddrModeBOrX, memOpnd->GetSize(), &newBaseOpnd, &newIndexOpnd, 0, false); nextInsn->SetOperand(kInsnSecondOpnd, newMemOpnd); } else { + auto *newOfstOpnd = &aarch64CGFunc->GetOrCreateOfstOpnd(0, k32BitSize); MemOperand &newMemOpnd = aarch64CGFunc->GetOrCreateMemOpnd(MemOperand::kAddrModeBOrX, memOpnd->GetSize(), &newBaseOpnd, - &newIndexOpnd, nullptr, nullptr); + &newIndexOpnd, newOfstOpnd, nullptr); nextInsn->SetOperand(kInsnSecondOpnd, newMemOpnd); } bb.RemoveInsn(insn); diff --git a/src/mapleall/maple_be/src/cg/cgfunc.cpp b/src/mapleall/maple_be/src/cg/cgfunc.cpp index cff6b87e7cfa6f574e82258107529495b97127b4..40e8c7974b3a9132532ae3006633159230e995f3 100644 --- a/src/mapleall/maple_be/src/cg/cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/cgfunc.cpp @@ -1576,8 +1576,12 @@ void CGFunc::CreateLmbcFormalParamInfo() { stackOffset += (typeSize + 7) & (-8); LmbcFormalParamInfo *info = GetMemoryPool()->New(primType, offset, typeSize); lmbcParamVec.push_back(info); + if (idx == 0 && func.IsFirstArgReturn()) { + info->SetIsReturn(); + } if (type->GetKind() == kTypeStruct) { - MIRStructType &structType = static_cast(*type); + MIRStructType *structType = static_cast(type); + info->SetType(structType); uint32 fpSize; uint32 numFpRegs = FloatParamRegRequired(structType, fpSize); if (numFpRegs > 0) { diff --git a/src/mapleall/maple_driver/src/driver_option_common.cpp b/src/mapleall/maple_driver/src/driver_option_common.cpp index b6fbedd5fa4645d1b4981d10e8638686a65cc766..b1a3adad065a6b55dbabe9b62482962ae9aac962 100644 --- a/src/mapleall/maple_driver/src/driver_option_common.cpp +++ b/src/mapleall/maple_driver/src/driver_option_common.cpp @@ -356,7 +356,7 @@ const mapleOption::Descriptor kUsages[] = { kArgCheckPolicyNone, " --genlmbc \tGenerate .lmbc file\n", "driver", - {} }, + { "mpl2mpl" } }, { kGenObj, kEnable, "c", diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 36ed2ee591ef8d12cafbf2a4544a066d29c2ee21..640f182959c9d737a7519c8d24fdaff92084d552 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -529,6 +529,17 @@ class MIRFunction { return codeMemPoolAllocator; } + TyIdx GetFuncRetStructTyIdx() { + TyIdx tyIdx = GetFormalDefAt(0).formalTyIdx; + MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx); + CHECK_FATAL(ty->GetKind() == kTypePointer, "Fake param not a pointer"); + MIRPtrType *pType = static_cast(ty); + tyIdx = pType->GetPointedTyIdx(); + CHECK_FATAL(GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->IsStructType(), + "Must be struct return type"); + return tyIdx; + } + void EnterFormals(); void NewBody(); diff --git a/src/mapleall/maple_ir/include/mir_type.h b/src/mapleall/maple_ir/include/mir_type.h index 972a0b301b22ad5d31778cc237c5615364e2af30..d6d32d999b227f92f7db32a8823419030f646c6c 100644 --- a/src/mapleall/maple_ir/include/mir_type.h +++ b/src/mapleall/maple_ir/include/mir_type.h @@ -666,6 +666,7 @@ struct OffsetType { }; class MIRStructType; // circular dependency exists, no other choice +class MIRFuncType; class MIRType { public: @@ -883,6 +884,19 @@ class MIRPtrType : public MIRType { hIdx += (typeAttrs.GetAttrFlag() << attrShift) + typeAttrs.GetAlignValue(); return hIdx % kTypeHashLength; } + bool IsFunctionPtr() { + MIRType *pointedType = GetPointedType(); + if (pointedType->GetKind() == kTypeFunction) { + return true; + } + if (pointedType->GetKind() == kTypePointer) { + MIRPtrType *pointedPtrType = static_cast(pointedType); + return pointedPtrType->GetPointedType()->GetKind() == kTypeFunction; + } + return false; + } + + MIRFuncType *GetPointedFuncType(); bool PointsToConstString() const override; diff --git a/src/mapleall/maple_ir/include/option.h b/src/mapleall/maple_ir/include/option.h index 823cabf6b10e1ef62cb965f1f3aaa93eda30d970..df211d9e35d63084a396954f712bc1b87b626eb9 100644 --- a/src/mapleall/maple_ir/include/option.h +++ b/src/mapleall/maple_ir/include/option.h @@ -177,6 +177,7 @@ class Options : public MapleDriverOptionBase { static bool sideEffect; static bool dumpIPA; static bool wpaa; + static bool genLMBC; private: void DecideMpl2MplRealLevel(const std::deque &inputOptions) const; diff --git a/src/mapleall/maple_ir/src/mir_type.cpp b/src/mapleall/maple_ir/src/mir_type.cpp index 53a4b08b8b9bc16497c21358876bc0b3093a324a..64ee74b164e73a10c60ab09f44293c1019d9f6c5 100644 --- a/src/mapleall/maple_ir/src/mir_type.cpp +++ b/src/mapleall/maple_ir/src/mir_type.cpp @@ -2284,6 +2284,20 @@ std::string MIRPtrType::GetCompactMplTypeName() const { return pointedType->GetCompactMplTypeName(); } +MIRFuncType *MIRPtrType::GetPointedFuncType() { + MIRType *pointedType = GetPointedType(); + if (pointedType->GetKind() == kTypeFunction) { + return static_cast(pointedType); + } + if (pointedType->GetKind() == kTypePointer) { + MIRPtrType *pointedPtrType = static_cast(pointedType); + if (pointedPtrType->GetPointedType()->GetKind() == kTypeFunction) { + return static_cast(pointedPtrType->GetPointedType()); + } + } + return nullptr; +} + uint32 MIRStructType::NumberOfFieldIDs() const { if (fieldsNum != kInvalidFieldNum) { return fieldsNum; diff --git a/src/mapleall/maple_ir/src/option.cpp b/src/mapleall/maple_ir/src/option.cpp index 2d532125b59977d256bcfbfafefb9c68b1ee40e7..ac8afaf260370d741688b363abbd9bdfb172f70a 100644 --- a/src/mapleall/maple_ir/src/option.cpp +++ b/src/mapleall/maple_ir/src/option.cpp @@ -67,6 +67,7 @@ bool Options::skipVirtualMethod = false; #endif bool Options::profileGen = false; bool Options::profileUse = false; +bool Options::genLMBC = false; // Ready to be deleted. bool Options::noRC = false; @@ -1355,6 +1356,9 @@ bool Options::SolveOptions(const std::deque