diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h --- a/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -19,6 +19,7 @@ namespace llvm { class StringRef; template class SmallString; +template class Expected; namespace XCOFF { @@ -296,7 +297,14 @@ StringRef getMappingClassString(XCOFF::StorageMappingClass SMC); StringRef getRelocationTypeString(XCOFF::RelocationType Type); -SmallString<32> parseParmsType(uint32_t Value, unsigned ParmsNum); +Expected> parseParmsType(uint32_t Value, unsigned FixedParmsNum, + unsigned FloatingParmsNum); +Expected> parseParmsTypeWithVecInfo(uint32_t Value, + unsigned FixedParmsNum, + unsigned FloatingParmsNum, + unsigned VectorParmsNum); +Expected> parseVectorParmsType(uint32_t Value, + unsigned ParmsNum); struct TracebackTable { enum LanguageID : uint8_t { @@ -391,6 +399,8 @@ static constexpr uint32_t ParmTypeIsVectorShortBit = 0x4000'0000; static constexpr uint32_t ParmTypeIsVectorIntBit = 0x8000'0000; static constexpr uint32_t ParmTypeIsVectorFloatBit = 0xC000'0000; + + static constexpr uint8_t WidthOfParamType = 2; }; // Extended Traceback table flags. diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -851,15 +851,17 @@ /// This checks that no defining machine operands exist for the register or /// any of its aliases. Definitions found on functions marked noreturn are /// ignored, to consider them pass 'true' for optional parameter - /// SkipNoReturnDef. The register is also considered modified when it is set - /// in the UsedPhysRegMask. - bool isPhysRegModified(MCRegister PhysReg, bool SkipNoReturnDef = false) const; + /// SkipNoReturnDef. if SkipTestUsedPhysRegMask is false, The register is also + /// considered modified when it is set in the UsedPhysRegMask. + bool isPhysRegModified(MCRegister PhysReg, bool SkipNoReturnDef = false, + bool SkipTestUsedPhysRegMask = false) const; /// Return true if the specified register is modified or read in this /// function. This checks that no machine operands exist for the register or - /// any of its aliases. The register is also considered used when it is set - /// in the UsedPhysRegMask. - bool isPhysRegUsed(MCRegister PhysReg) const; + /// any of its aliases. if SkipTestUsedPhysRegMask is false, The register is + /// also considered used when it is set in the UsedPhysRegMask. + bool isPhysRegUsed(MCRegister PhysReg, + bool SkipTestUsedPhysRegMask = false) const; /// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used. /// This corresponds to the bit mask attached to register mask operands. diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -397,20 +397,19 @@ }; class TBVectorExt { - friend class XCOFFTracebackTable; - uint16_t Data; - uint32_t VecParmsInfo; + SmallString<32> VecParmsInfo; - TBVectorExt(StringRef TBvectorStrRef); + TBVectorExt(StringRef TBvectorStrRef, Error &Err); public: + static Expected create(StringRef TBvectorStrRef); uint8_t getNumberOfVRSaved() const; bool isVRSavedOnStack() const; bool hasVarArgs() const; uint8_t getNumberOfVectorParms() const; bool hasVMXInstruction() const; - SmallString<32> getVectorParmsInfoString() const; + SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; }; }; /// This class provides methods to extract traceback table data from a buffer. diff --git a/llvm/lib/BinaryFormat/XCOFF.cpp b/llvm/lib/BinaryFormat/XCOFF.cpp --- a/llvm/lib/BinaryFormat/XCOFF.cpp +++ b/llvm/lib/BinaryFormat/XCOFF.cpp @@ -9,6 +9,8 @@ #include "llvm/BinaryFormat/XCOFF.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" using namespace llvm; @@ -76,6 +78,7 @@ } return "Unknown"; } +#undef RELOC_CASE #define LANG_CASE(A) \ case XCOFF::TracebackTable::A: \ @@ -104,15 +107,25 @@ } #undef LANG_CASE -SmallString<32> XCOFF::parseParmsType(uint32_t Value, unsigned ParmsNum) { +Expected> XCOFF::parseParmsType(uint32_t Value, + unsigned FixedParmsNum, + unsigned FloatingParmsNum) { SmallString<32> ParmsType; - for (unsigned I = 0; I < ParmsNum; ++I) { - if (I != 0) + int Bits = 0; + unsigned ParsedFixedNum = 0; + unsigned ParsedFloatingNum = 0; + unsigned ParsedNum = 0; + unsigned ParmsNum = FixedParmsNum + FloatingParmsNum; + + while (Bits < 32 && ParsedNum < ParmsNum) { + if (++ParsedNum > 1) ParmsType += ", "; if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { // Fixed parameter type. ParmsType += "i"; + ++ParsedFixedNum; Value <<= 1; + ++Bits; } else { if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0) // Float parameter type. @@ -120,12 +133,23 @@ else // Double parameter type. ParmsType += "d"; - + ++ParsedFloatingNum; Value <<= 2; + Bits += 2; } } - assert(Value == 0u && "ParmsType encodes more than ParmsNum parameters."); - return ParmsType; + + // We have more parameters than the 32 Bits could encode. + if (ParsedNum < ParmsNum) + ParmsType += ", ..."; + + if (Value != 0u || (ParsedFixedNum > FixedParmsNum) || + (ParsedFloatingNum > FloatingParmsNum)) + return createStringError(errc::invalid_argument, + "ParmsType encodes can not map to ParmsNum " + "parameters in parseParmsType."); + else + return ParmsType; } SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) { @@ -153,4 +177,95 @@ return Res; } -#undef RELOC_CASE +Expected> +XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, + unsigned FloatingParmsNum, + unsigned VectorParmsNum) { + SmallString<32> ParmsType; + + unsigned ParsedFixedNum = 0; + unsigned ParsedFloatingNum = 0; + unsigned ParsedVectorNum = 0; + unsigned ParsedNum = 0; + unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum; + + for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) { + if (++ParsedNum > 1) + ParmsType += ", "; + + switch (Value & TracebackTable::ParmTypeMask) { + case TracebackTable::ParmTypeIsFixedBits: + ParmsType += "i"; + ++ParsedFixedNum; + break; + case TracebackTable::ParmTypeIsVectorBits: + ParmsType += "v"; + ++ParsedVectorNum; + break; + case TracebackTable::ParmTypeIsFloatingBits: + ParmsType += "f"; + ++ParsedFloatingNum; + break; + case TracebackTable::ParmTypeIsDoubleBits: + ParmsType += "d"; + ++ParsedFloatingNum; + break; + default: + assert(false && "Unrecognized bits in ParmsType."); + } + Value <<= 2; + } + + // We have more parameters than the 32 Bits could encode. + if (ParsedNum < ParmsNum) + ParmsType += ", ..."; + + if (Value != 0u || ParsedFixedNum > FixedParmsNum || + ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum) + return createStringError( + errc::invalid_argument, + "ParmsType encodes can not map to ParmsNum parameters " + "in parseParmsTypeWithVecInfo."); + + return ParmsType; +} + +Expected> XCOFF::parseVectorParmsType(uint32_t Value, + unsigned ParmsNum) { + SmallString<32> ParmsType; + unsigned ParsedNum = 0; + for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) { + if (++ParsedNum > 1) + ParmsType += ", "; + switch (Value & TracebackTable::ParmTypeMask) { + case TracebackTable::ParmTypeIsVectorCharBit: + ParmsType += "vc"; + break; + + case TracebackTable::ParmTypeIsVectorShortBit: + ParmsType += "vs"; + break; + + case TracebackTable::ParmTypeIsVectorIntBit: + ParmsType += "vi"; + break; + + case TracebackTable::ParmTypeIsVectorFloatBit: + ParmsType += "vf"; + break; + } + + Value <<= 2; + } + + // We have more parameters than the 32 Bits could encode. + if (ParsedNum < ParmsNum) + ParmsType += ", ..."; + + if (Value != 0u) + return createStringError(errc::invalid_argument, + "ParmsType encodes more than ParmsNum parameters " + "in parseVectorParmsType."); + else + return ParmsType; +} diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -567,9 +567,10 @@ !Called->hasFnAttribute(Attribute::NoUnwind)); } -bool MachineRegisterInfo::isPhysRegModified(MCRegister PhysReg, - bool SkipNoReturnDef) const { - if (UsedPhysRegMask.test(PhysReg)) +bool MachineRegisterInfo::isPhysRegModified( + MCRegister PhysReg, bool SkipNoReturnDef, + bool SkipTestUsedPhysRegMask) const { + if (!SkipTestUsedPhysRegMask && UsedPhysRegMask.test(PhysReg)) return true; const TargetRegisterInfo *TRI = getTargetRegisterInfo(); for (MCRegAliasIterator AI(PhysReg, TRI, true); AI.isValid(); ++AI) { @@ -582,8 +583,9 @@ return false; } -bool MachineRegisterInfo::isPhysRegUsed(MCRegister PhysReg) const { - if (UsedPhysRegMask.test(PhysReg)) +bool MachineRegisterInfo::isPhysRegUsed(MCRegister PhysReg, + bool SkipTestUsedPhysRegMask) const { + if (!SkipTestUsedPhysRegMask && UsedPhysRegMask.test(PhysReg)) return true; const TargetRegisterInfo *TRI = getTargetRegisterInfo(); for (MCRegAliasIterator AliasReg(PhysReg, TRI, true); AliasReg.isValid(); diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -861,15 +861,34 @@ return support::endian::read32be(Bytes.data()) == 0; } -TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) { +#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) +#define GETVALUEWITHMASKSHIFT(X, S) \ + ((Data & (TracebackTable::X)) >> (TracebackTable::S)) + +Expected TBVectorExt::create(StringRef TBvectorStrRef) { + Error Err = Error::success(); + TBVectorExt TBTVecExt(TBvectorStrRef, Err); + if (Err) + return std::move(Err); + return TBTVecExt; +} + +TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { const uint8_t *Ptr = reinterpret_cast(TBvectorStrRef.data()); Data = support::endian::read16be(Ptr); - VecParmsInfo = support::endian::read32be(Ptr + 2); + uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); + unsigned ParmsNum = + GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); + + ErrorAsOutParameter EAO(&Err); + Expected> VecParmsTypeOrError = + parseVectorParmsType(VecParmsTypeValue, ParmsNum); + if (!VecParmsTypeOrError) + Err = VecParmsTypeOrError.takeError(); + else + VecParmsInfo = VecParmsTypeOrError.get(); } -#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) -#define GETVALUEWITHMASKSHIFT(X, S) \ - ((Data & (TracebackTable::X)) >> (TracebackTable::S)) uint8_t TBVectorExt::getNumberOfVRSaved() const { return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); } @@ -881,6 +900,7 @@ bool TBVectorExt::hasVarArgs() const { return GETVALUEWITHMASK(HasVarArgsMask); } + uint8_t TBVectorExt::getNumberOfVectorParms() const { return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); @@ -892,72 +912,6 @@ #undef GETVALUEWITHMASK #undef GETVALUEWITHMASKSHIFT -SmallString<32> TBVectorExt::getVectorParmsInfoString() const { - SmallString<32> ParmsType; - uint32_t Value = VecParmsInfo; - for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) { - if (I != 0) - ParmsType += ", "; - switch (Value & TracebackTable::ParmTypeMask) { - case TracebackTable::ParmTypeIsVectorCharBit: - ParmsType += "vc"; - break; - - case TracebackTable::ParmTypeIsVectorShortBit: - ParmsType += "vs"; - break; - - case TracebackTable::ParmTypeIsVectorIntBit: - ParmsType += "vi"; - break; - - case TracebackTable::ParmTypeIsVectorFloatBit: - ParmsType += "vf"; - break; - } - Value <<= 2; - } - return ParmsType; -} - -static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value, - unsigned int ParmsNum) { - SmallString<32> ParmsType; - unsigned I = 0; - bool Begin = false; - while (I < ParmsNum || Value) { - if (Begin) - ParmsType += ", "; - else - Begin = true; - - switch (Value & TracebackTable::ParmTypeMask) { - case TracebackTable::ParmTypeIsFixedBits: - ParmsType += "i"; - ++I; - break; - case TracebackTable::ParmTypeIsVectorBits: - ParmsType += "v"; - break; - case TracebackTable::ParmTypeIsFloatingBits: - ParmsType += "f"; - ++I; - break; - case TracebackTable::ParmTypeIsDoubleBits: - ParmsType += "d"; - ++I; - break; - default: - assert(false && "Unrecognized bits in ParmsType."); - } - Value <<= 2; - } - assert(I == ParmsNum && - "The total parameters number of fixed-point or floating-point " - "parameters not equal to the number in the parameter type!"); - return ParmsType; -} - Expected XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size) { Error Err = Error::success(); @@ -978,21 +932,13 @@ // Skip 8 bytes of mandatory fields. DE.getU64(Cur); + unsigned FixedParmsNum = getNumberOfFixedParms(); + unsigned FloatingParmsNum = getNumberOfFPParms(); + uint32_t ParamsTypeValue = 0; + // Begin to parse optional fields. - if (Cur) { - unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms(); - - // As long as there are no "fixed-point" or floating-point parameters, this - // field remains not present even when hasVectorInfo gives true and - // indicates the presence of vector parameters. - if (ParmNum > 0) { - uint32_t ParamsTypeValue = DE.getU32(Cur); - if (Cur) - ParmsType = hasVectorInfo() - ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum) - : parseParmsType(ParamsTypeValue, ParmNum); - } - } + if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) + ParamsTypeValue = DE.getU32(Cur); if (Cur && hasTraceBackTableOffset()) TraceBackTableOffset = DE.getU32(Cur); @@ -1021,10 +967,35 @@ if (Cur && isAllocaUsed()) AllocaRegister = DE.getU8(Cur); + unsigned VectorParmsNum = 0; if (Cur && hasVectorInfo()) { StringRef VectorExtRef = DE.getBytes(Cur, 6); - if (Cur) - VecExt = TBVectorExt(VectorExtRef); + if (Cur) { + Expected TBVecExtOrErr = TBVectorExt::create(VectorExtRef); + if (!TBVecExtOrErr) { + Err = TBVecExtOrErr.takeError(); + return; + } + VecExt = TBVecExtOrErr.get(); + VectorParmsNum = VecExt.getValue().getNumberOfVectorParms(); + } + } + + // As long as there are no "fixed-point" or floating-point parameters, this + // field remains not present even when hasVectorInfo gives true and + // indicates the presence of vector parameters. + if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { + Expected> ParmsTypeOrError = + hasVectorInfo() + ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, + FloatingParmsNum, VectorParmsNum) + : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); + + if (!ParmsTypeOrError) { + Err = ParmsTypeOrError.takeError(); + return; + } + ParmsType = ParmsTypeOrError.get(); } if (Cur && hasExtensionTable()) @@ -1032,6 +1003,7 @@ if (!Cur) Err = Cur.takeError(); + Size = Cur.tell(); } diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -61,6 +61,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" #include "llvm/Support/TargetRegistry.h" @@ -1957,7 +1958,7 @@ // Check the function uses floating-point processor instructions or not for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) { - if (MRI.isPhysRegUsed(Reg)) { + if (MRI.isPhysRegUsed(Reg, true)) { FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask; break; } @@ -1997,7 +1998,7 @@ FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask; static_assert(XCOFF::AllocRegNo == 31, "Unexpected register usage!"); - if (MRI.isPhysRegUsed(Subtarget->isPPC64() ? PPC::X31 : PPC::R31)) + if (MRI.isPhysRegUsed(Subtarget->isPPC64() ? PPC::X31 : PPC::R31, true)) FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask; const SmallVectorImpl &MustSaveCRs = FI->getMustSaveCRs(); @@ -2027,7 +2028,7 @@ uint32_t FPRSaved = 0; for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) { - if (MRI.isPhysRegModified(Reg)) { + if (MRI.isPhysRegModified(Reg, false, true)) { FPRSaved = PPC::F31 - Reg + 1; break; } @@ -2042,6 +2043,19 @@ (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1); // Set the 6th byte of mandatory field. + + // Check whether has Vector Instruction + bool HasVectorInst = false; + for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg) + if (MRI.isPhysRegUsed(Reg, true)) { + // Has VMX instruction. + HasVectorInst = true; + break; + } + + if (FI->hasVectorParms() || HasVectorInst) + SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask; + bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF); if (ShouldEmitEHBlock) SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask; @@ -2053,7 +2067,7 @@ unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31; for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) { - if (MRI.isPhysRegModified(Reg)) { + if (MRI.isPhysRegModified(Reg, false, true)) { GPRSaved = GPREnd - Reg + 1; break; } @@ -2070,9 +2084,9 @@ (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1); // Set the 7th byte of mandatory field. - uint32_t NumberOfFixedPara = FI->getFixedParamNum(); + uint32_t NumberOfFixedParms = FI->getFixedParmsNum(); SecondHalfOfMandatoryField |= - (NumberOfFixedPara << TracebackTable::NumberOfFixedParmsShift) & + (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) & TracebackTable::NumberOfFixedParmsMask; GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField, NumberOfFixedParms); @@ -2085,9 +2099,9 @@ // Always set parameter on stack. SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask; - uint32_t NumberOfFPPara = FI->getFloatingPointParamNum(); + uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum(); SecondHalfOfMandatoryField |= - (NumberOfFPPara << TracebackTable::NumberOfFloatingPointParmsShift) & + (NumberOfFPParms << TracebackTable::NumberOfFloatingPointParmsShift) & TracebackTable::NumberOfFloatingPointParmsMask; GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField, @@ -2100,18 +2114,25 @@ // Generate the optional fields of traceback table. // Parameter type. - if (NumberOfFixedPara || NumberOfFPPara) { - assert((SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) == - 0 && - "VectorInfo has not been implemented."); - uint32_t ParaType = FI->getParameterType(); - CommentOS << "Parameter type = " - << XCOFF::parseParmsType(ParaType, - NumberOfFixedPara + NumberOfFPPara); - EmitComment(); - OutStreamer->emitIntValueInHexWithPadding(ParaType, sizeof(ParaType)); + if (NumberOfFixedParms || NumberOfFPParms) { + uint32_t ParmsTypeValue = FI->getParmsType(); + + Expected> ParmsType = + FI->hasVectorParms() + ? XCOFF::parseParmsTypeWithVecInfo( + ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms, + FI->getVectorParmsNum()) + : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms, + NumberOfFPParms); + + assert(ParmsType && toString(ParmsType.takeError()).c_str()); + if (ParmsType) { + CommentOS << "Parameter type = " << ParmsType.get(); + EmitComment(); + } + OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue, + sizeof(ParmsTypeValue)); } - // Traceback table offset. OutStreamer->AddComment("Function size"); if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) { @@ -2143,6 +2164,70 @@ OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg)); } + if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) { + uint16_t VRData = 0; + // Calculate the number of VRs be saved. + // Vector registers 20 through 31 are marked as reserved and cannot be used + // in the default ABI. + const PPCSubtarget &Subtarget = MF->getSubtarget(); + if (Subtarget.isAIXABI() && Subtarget.hasAltivec() && + TM.getAIXExtendedAltivecABI()) { + for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg) + if (MRI.isPhysRegModified(Reg, false, true)) { + // Number of VRs saved. + VRData |= + ((PPC::V31 - Reg + 1) << TracebackTable::NumberOfVRSavedShift) & + TracebackTable::NumberOfVRSavedMask; + // This bit is supposed to set only when the special register + // VRSAVE is saved on stack. + // However, IBM XL compiler sets the bit when any vector registers + // are saved on the stack. We will follow XL's behavior on AIX + // so that we don't get surprise behavior change for C code. + VRData |= TracebackTable::IsVRSavedOnStackMask; + break; + } + } + + // Set has_varargs. + if (FI->getVarArgsFrameIndex()) + VRData |= TracebackTable::HasVarArgsMask; + + // Vector parameters number. + unsigned VectorParmsNum = FI->getVectorParmsNum(); + VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) & + TracebackTable::NumberOfVectorParmsMask; + + for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg) + if (!MRI.reg_nodbg_empty(Reg)) { + // Has VMX instruction. + VRData |= TracebackTable::HasVMXInstructionMask; + break; + } + + GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved); + GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack); + GENBOOLCOMMENT(", ", VRData, HasVarArgs); + EmitComment(); + OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1); + + GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms); + GENBOOLCOMMENT(", ", VRData, HasVMXInstruction); + EmitComment(); + OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1); + + uint32_t VecParmTypeValue = FI->getVecExtParmsType(); + + Expected> VecParmsType = + XCOFF::parseVectorParmsType(VecParmTypeValue, VectorParmsNum); + assert(VecParmsType && toString(VecParmsType.takeError()).c_str()); + if (VecParmsType) { + CommentOS << "Vector Parameter type = " << VecParmsType.get(); + EmitComment(); + } + OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue, + sizeof(VecParmTypeValue)); + } + uint8_t ExtensionTableFlag = 0; if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) { if (ShouldEmitEHBlock) @@ -2170,7 +2255,6 @@ OutStreamer->AddComment("EHInfo Table"); OutStreamer->emitValue(Exp, DL.getPointerSize()); } - #undef GENBOOLCOMMENT #undef GENVALUECOMMENT } diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -7080,10 +7080,38 @@ if (VA.isRegLoc()) { if (VA.getValVT().isScalarInteger()) FuncInfo->appendParameterType(PPCFunctionInfo::FixedType); - else if (VA.getValVT().isFloatingPoint() && !VA.getValVT().isVector()) - FuncInfo->appendParameterType(VA.getValVT().SimpleTy == MVT::f32 - ? PPCFunctionInfo::ShortFloatPoint - : PPCFunctionInfo::LongFloatPoint); + else if (VA.getValVT().isFloatingPoint() && !VA.getValVT().isVector()) { + switch (VA.getValVT().SimpleTy) { + default: + report_fatal_error("Unhandled value type for argument."); + case MVT::f32: + FuncInfo->appendParameterType(PPCFunctionInfo::ShortFloatingPoint); + break; + case MVT::f64: + FuncInfo->appendParameterType(PPCFunctionInfo::LongFloatingPoint); + break; + } + } else if (VA.getValVT().isVector()) { + switch (VA.getValVT().SimpleTy) { + default: + report_fatal_error("Unhandled value type for argument."); + case MVT::v16i8: + FuncInfo->appendParameterType(PPCFunctionInfo::VectorChar); + break; + case MVT::v8i16: + FuncInfo->appendParameterType(PPCFunctionInfo::VectorShort); + break; + case MVT::v4i32: + case MVT::v2i64: + case MVT::v1i128: + FuncInfo->appendParameterType(PPCFunctionInfo::VectorInt); + break; + case MVT::v4f32: + case MVT::v2f64: + FuncInfo->appendParameterType(PPCFunctionInfo::VectorFloat); + break; + } + } } if (Flags.isByVal() && VA.isMemLoc()) { diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h --- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h +++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h @@ -23,12 +23,14 @@ /// PowerPC target-specific information for each MachineFunction. class PPCFunctionInfo : public MachineFunctionInfo { public: - // The value in the ParamType are used to indicate the bitstrings used in the - // encoding format. enum ParamType { - FixedType = 0x0, - ShortFloatPoint = 0x2, - LongFloatPoint = 0x3 + FixedType, + ShortFloatingPoint, + LongFloatingPoint, + VectorChar, + VectorShort, + VectorInt, + VectorFloat }; private: @@ -120,19 +122,20 @@ /// register for parameter passing. unsigned VarArgsNumFPR = 0; - /// FixedParamNum - Number of fixed parameter. - unsigned FixedParamNum = 0; + /// HasVectorParms - True if ther are vector parameters + bool HasVectorParms = false; - /// FloatingParamNum - Number of floating point parameter. - unsigned FloatingPointParamNum = 0; + /// FixedParmsNum - The number of fixed parameters + unsigned FixedParmsNum = 0; - /// ParamType - Encode type for every parameter - /// in the order of parameters passing in. - /// Bitstring starts from the most significant (leftmost) bit. - /// '0'b => fixed parameter. - /// '10'b => floating point short parameter. - /// '11'b => floating point long parameter. - uint32_t ParameterType = 0; + /// FloatingParmsNum - The number of floating parameters + unsigned FloatingParmsNum = 0; + + /// VectorParmsNum - The number of vector parameters + unsigned VectorParmsNum = 0; + + /// ParamTypes - Store all the paramters type. + SmallVector ParamtersType; /// CRSpillFrameIndex - FrameIndex for CR spill slot for 32-bit SVR4. int CRSpillFrameIndex = 0; @@ -224,11 +227,15 @@ unsigned getVarArgsNumGPR() const { return VarArgsNumGPR; } void setVarArgsNumGPR(unsigned Num) { VarArgsNumGPR = Num; } - unsigned getFixedParamNum() const { return FixedParamNum; } + unsigned getFixedParmsNum() const { return FixedParmsNum; } + unsigned getFloatingPointParmsNum() const { return FloatingParmsNum; } + unsigned getVectorParmsNum() const { return VectorParmsNum; } + bool hasVectorParms() const { return HasVectorParms; } + + uint32_t getParmsType() const; - unsigned getFloatingPointParamNum() const { return FloatingPointParamNum; } + uint32_t getVecExtParmsType() const; - uint32_t getParameterType() const { return ParameterType; } void appendParameterType(ParamType Type); unsigned getVarArgsNumFPR() const { return VarArgsNumFPR; } diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.cpp b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.cpp @@ -66,34 +66,122 @@ } void PPCFunctionInfo::appendParameterType(ParamType Type) { - uint32_t CopyParamType = ParameterType; - int Bits = 0; + if (!HasVectorParms && (Type >= VectorChar && Type <= VectorFloat)) + HasVectorParms = true; + + ParamtersType.push_back(Type); + if (Type >= ShortFloatingPoint && Type <= LongFloatingPoint) { + ++FloatingParmsNum; + return; + } - // If it is fixed type, we only need to increase the FixedParamNum, for - // the bit encode of fixed type is bit of zero, we do not need to change the - // ParamType. if (Type == FixedType) { - ++FixedParamNum; + ++FixedParmsNum; return; } - ++FloatingPointParamNum; + if (Type >= VectorChar && Type <= VectorFloat) + ++VectorParmsNum; +} + +uint32_t PPCFunctionInfo::getVecExtParmsType() const { + + uint32_t VectExtParamInfo = 0; + unsigned ShiftBits = 32 - XCOFF::TracebackTable::WidthOfParamType; + int Bits = 0; + + if (!HasVectorParms) + return 0; + + for (const auto &Elt : ParamtersType) { + switch (Elt) { + case VectorChar: + VectExtParamInfo <<= XCOFF::TracebackTable::WidthOfParamType; + VectExtParamInfo |= + XCOFF::TracebackTable::ParmTypeIsVectorCharBit >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; + case VectorShort: + VectExtParamInfo <<= XCOFF::TracebackTable::WidthOfParamType; + VectExtParamInfo |= + XCOFF::TracebackTable::ParmTypeIsVectorShortBit >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; + case VectorInt: + VectExtParamInfo <<= XCOFF::TracebackTable::WidthOfParamType; + VectExtParamInfo |= + XCOFF::TracebackTable::ParmTypeIsVectorIntBit >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; + case VectorFloat: + VectExtParamInfo <<= XCOFF::TracebackTable::WidthOfParamType; + VectExtParamInfo |= + XCOFF::TracebackTable::ParmTypeIsVectorFloatBit >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; + default: + break; + } + + // There are only 32bits in the VectExtParamInfo. + if (Bits >= 32) + break; + } + return Bits < 32 ? VectExtParamInfo << (32 - Bits) : VectExtParamInfo; +} + +uint32_t PPCFunctionInfo::getParmsType() const { + uint32_t ParamsTypeInfo = 0; + unsigned ShiftBits = 32 - XCOFF::TracebackTable::WidthOfParamType; + + int Bits = 0; + for (const auto &Elt : ParamtersType) { + + if (Elt == FixedType && !HasVectorParms && Bits > 31) + break; + if ((Elt != FixedType || HasVectorParms) && Bits > 30) + break; - for (int I = 0; - I < static_cast(FloatingPointParamNum + FixedParamNum - 1); ++I) { - if (CopyParamType & XCOFF::TracebackTable::ParmTypeIsFloatingBit) { + switch (Elt) { + case FixedType: + if (HasVectorParms) { + //'00' ==> fixed parameter if HasVectorParms is true. + ParamsTypeInfo <<= XCOFF::TracebackTable::WidthOfParamType; + ParamsTypeInfo |= + XCOFF::TracebackTable::ParmTypeIsFixedBits >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + } else { + //'0' ==> fixed parameter if HasVectorParms is false. + ParamsTypeInfo <<= 1; + ++Bits; + } + break; + case ShortFloatingPoint: // '10'b => floating point short parameter. + ParamsTypeInfo <<= XCOFF::TracebackTable::WidthOfParamType; + ParamsTypeInfo |= + XCOFF::TracebackTable::ParmTypeIsFloatingBits >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; + case LongFloatingPoint: // '11'b => floating point long parameter. - CopyParamType <<= 2; - Bits += 2; - } else { - // '0'b => fixed parameter. - CopyParamType <<= 1; - ++Bits; + ParamsTypeInfo <<= XCOFF::TracebackTable::WidthOfParamType; + ParamsTypeInfo |= + XCOFF::TracebackTable::ParmTypeIsDoubleBits >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; + case VectorChar: + case VectorShort: + case VectorInt: + case VectorFloat: + // '01' ==> vector parameter + ParamsTypeInfo <<= XCOFF::TracebackTable::WidthOfParamType; + ParamsTypeInfo |= + XCOFF::TracebackTable::ParmTypeIsVectorBits >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + break; } } - assert(Type != FixedType && "FixedType should already be handled."); - if (Bits < 31) - ParameterType |= Type << (30 - Bits); + return Bits < 32 ? ParamsTypeInfo << (32 - Bits) : ParamsTypeInfo; } diff --git a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll --- a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll +++ b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-clobber-register.ll @@ -1,9 +1,9 @@ ; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ -; RUN: -mattr=-altivec -xcoff-traceback-table=true < %s | \ +; RUN: -mattr=+altivec -vec-extabi -xcoff-traceback-table=true < %s | \ ; RUN: FileCheck --check-prefixes=CHECK-ASM,COMMON %s ; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -function-sections \ -; RUN: -mcpu=pwr4 -mattr=-altivec < %s | \ +; RUN: -mcpu=pwr4 -mattr=+altivec -vec-extabi < %s | \ ; RUN: FileCheck --check-prefixes=CHECK-FUNC,COMMON %s define float @bar() #0 { @@ -26,6 +26,16 @@ ret float %add } +define <4 x i32> @foov() #0 { +entry: + %taken = alloca <4 x i32>, align 16 + %data = alloca <4 x i32>, align 16 + store <4 x i32> , <4 x i32>* %data, align 16 + call void asm sideeffect "", "~{v31},~{v30},~{v29},~{v28}"() + %0 = load <4 x i32>, <4 x i32>* %taken, align 16 + ret <4 x i32> %0 +} + ; COMMON: .vbyte 4, 0x00000000 # Traceback table begin ; COMMON-NEXT: .byte 0x00 # Version = 0 ; COMMON-NEXT: .byte 0x09 # Language = CPlusPlus @@ -46,3 +56,27 @@ ; COMMON-NEXT: .byte "bar" # Function Name ; COMMON-NEXT: .byte 0x1f # AllocaUsed ; COMMON-NEXT: # -- End function + +; COMMON: L..foov0: +; COMMON-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; COMMON-NEXT: .byte 0x00 # Version = 0 +; COMMON-NEXT: .byte 0x09 # Language = CPlusPlus +; COMMON-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; COMMON-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; COMMON-NEXT: # -HasControlledStorage, -IsTOCless +; COMMON-NEXT: # -IsFloatingPointPresent +; COMMON-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; COMMON-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; COMMON-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; COMMON-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; COMMON-NEXT: .byte 0x80 # +HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; COMMON-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; COMMON-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; CHECK-ASM-NEXT: .vbyte 4, L..foov0-.foov # Function size +; CHECK-FUNC-NEXT: .vbyte 4, L..foov0-.foov[PR] # Function size +; COMMON-NEXT: .vbyte 2, 0x0004 # Function name len = 4 +; COMMON-NEXT: .byte "foov" # Function Name +; COMMON-NEXT: .byte 0x12 # NumOfVRsSaved = 4, +IsVRSavedOnStack, -HasVarArgs +; COMMON-NEXT: .byte 0x01 # NumOfVectorParams = 0, +HasVMXInstruction +; COMMON-NEXT: .vbyte 4, 0x00000000 # Vector Parameter type = +; COMMON-NEXT: # -- End function diff --git a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-vectorinfo.ll b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-vectorinfo.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-vectorinfo.ll @@ -0,0 +1,127 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr7 \ +; RUN: -mattr=+altivec -vec-extabi -xcoff-traceback-table=true < %s | \ +; RUN: FileCheck --check-prefixes=CHECK-ASM,COMMON %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -function-sections \ +; RUN: -mcpu=pwr7 -mattr=+altivec -vec-extabi < %s | \ +; RUN: FileCheck --check-prefixes=CHECK-FUNC,COMMON %s + +;; #include +;; vector float f(vector int vi1, int i1, int i2, float f1, vector float vf,double d1, vector char vc1) { +;; return vec_abs(vf); +;; } +;; vector float fin(int x) { +;; vector float vf ={1.0,1.0,1.0,1.0}; +;; if (x) return vf; +;; return vec_abs(vf); +;; } + +define dso_local <4 x float> @f(<4 x i32> %vi1, i32 signext %i1, i32 signext %i2, float %f1, <4 x float> %vf, double %d1, <16 x i8> %vc1) #0 { +entry: + %__a.addr.i = alloca <4 x float>, align 16 + %vi1.addr = alloca <4 x i32>, align 16 + %i1.addr = alloca i32, align 4 + %i2.addr = alloca i32, align 4 + %f1.addr = alloca float, align 4 + %vf.addr = alloca <4 x float>, align 16 + %d1.addr = alloca double, align 8 + %vc1.addr = alloca <16 x i8>, align 16 + store <4 x i32> %vi1, <4 x i32>* %vi1.addr, align 16 + store i32 %i1, i32* %i1.addr, align 4 + store i32 %i2, i32* %i2.addr, align 4 + store float %f1, float* %f1.addr, align 4 + store <4 x float> %vf, <4 x float>* %vf.addr, align 16 + store double %d1, double* %d1.addr, align 8 + store <16 x i8> %vc1, <16 x i8>* %vc1.addr, align 16 + %0 = load <4 x float>, <4 x float>* %vf.addr, align 16 + store <4 x float> %0, <4 x float>* %__a.addr.i, align 16 + %1 = load <4 x float>, <4 x float>* %__a.addr.i, align 16 + %2 = load <4 x float>, <4 x float>* %__a.addr.i, align 16 + %3 = call <4 x float> @llvm.fabs.v4f32(<4 x float> %2) #2 + ret <4 x float> %3 +} + +define <4 x float> @fin(i32 %x) #0 { +entry: + %__a.addr.i = alloca <4 x float>, align 16 + %__res.i = alloca <4 x i32>, align 16 + %retval = alloca <4 x float>, align 16 + %x.addr = alloca i32, align 4 + %vf = alloca <4 x float>, align 16 + store i32 %x, i32* %x.addr, align 4 + store <4 x float> , <4 x float>* %vf, align 16 + %0 = load i32, i32* %x.addr, align 4 + %tobool = icmp ne i32 %0, 0 + br i1 %tobool, label %if.then, label %if.end + +if.then: ; preds = %entry + %1 = load <4 x float>, <4 x float>* %vf, align 16 + store <4 x float> %1, <4 x float>* %retval, align 16 + br label %return + +if.end: ; preds = %entry + %2 = load <4 x float>, <4 x float>* %vf, align 16 + store <4 x float> %2, <4 x float>* %__a.addr.i, align 16 + %3 = load <4 x float>, <4 x float>* %__a.addr.i, align 16 + %4 = bitcast <4 x float> %3 to <4 x i32> + %and.i = and <4 x i32> %4, + store <4 x i32> %and.i, <4 x i32>* %__res.i, align 16 + %5 = load <4 x i32>, <4 x i32>* %__res.i, align 16 + %6 = bitcast <4 x i32> %5 to <4 x float> + store <4 x float> %6, <4 x float>* %retval, align 16 + br label %return + +return: ; preds = %if.end, %if.then + %7 = load <4 x float>, <4 x float>* %retval, align 16 + ret <4 x float> %7 +} + +declare <4 x float> @llvm.fabs.v4f32(<4 x float>) #1 + +; COMMON: L..f0: +; COMMON-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; COMMON-NEXT: .byte 0x00 # Version = 0 +; COMMON-NEXT: .byte 0x09 # Language = CPlusPlus +; COMMON-NEXT: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; COMMON-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; COMMON-NEXT: # -HasControlledStorage, -IsTOCless +; COMMON-NEXT: # +IsFloatingPointPresent +; COMMON-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; COMMON-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; COMMON-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; COMMON-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; COMMON-NEXT: .byte 0x80 # +HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; COMMON-NEXT: .byte 0x02 # NumberOfFixedParms = 2 +; COMMON-NEXT: .byte 0x05 # NumberOfFPParms = 2, +HasParmsOnStack +; COMMON-NEXT: .vbyte 4, 0x42740000 # Parameter type = v, i, i, f, v, d, v +; CHECK-ASM-NEXT: .vbyte 4, L..f0-.f # Function size +; CHECK-FUNC-NEXT: .vbyte 4, L..f0-.f[PR] # Function size +; COMMON-NEXT: .vbyte 2, 0x0001 # Function name len = 1 +; COMMON-NEXT: .byte 102 # Function Name +; COMMON-NEXT: .byte 0x00 # NumOfVRsSaved = 0, -IsVRSavedOnStack, -HasVarArgs +; COMMON-NEXT: .byte 0x07 # NumOfVectorParams = 3, +HasVMXInstruction +; COMMON-NEXT: .vbyte 4, 0xb0000000 # Vector Parameter type = vi, vf, vc + +; COMMON: L..fin0: +; COMMON-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; COMMON-NEXT: .byte 0x00 # Version = 0 +; COMMON-NEXT: .byte 0x09 # Language = CPlusPlus +; COMMON-NEXT: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; COMMON-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; COMMON-NEXT: # -HasControlledStorage, -IsTOCless +; COMMON-NEXT: # +IsFloatingPointPresent +; COMMON-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; COMMON-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; COMMON-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; COMMON-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; COMMON-NEXT: .byte 0x80 # +HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; COMMON-NEXT: .byte 0x01 # NumberOfFixedParms = 1 +; COMMON-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; COMMON-NEXT: .vbyte 4, 0x00000000 # Parameter type = i +; CHECK-ASM-NEXT: .vbyte 4, L..fin0-.fin # Function size +; CHECK-FUNC-NEXT: .vbyte 4, L..fin0-.fin[PR] # Function size +; COMMON-NEXT: .vbyte 2, 0x0003 # Function name len = 3 +; COMMON-NEXT: .byte "fin" # Function Name +; COMMON-NEXT: .byte 0x00 # NumOfVRsSaved = 0, -IsVRSavedOnStack, -HasVarArgs +; COMMON-NEXT: .byte 0x01 # NumOfVectorParams = 0, +HasVMXInstruction +; COMMON-NEXT: .vbyte 4, 0x00000000 # Vector Parameter type = diff --git a/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-vectorinfo_hasvarg.ll b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-vectorinfo_hasvarg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-emit-tracebacktable-vectorinfo_hasvarg.ll @@ -0,0 +1,35 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr7 \ +; RUN: -mattr=+altivec -vec-extabi -xcoff-traceback-table=true 2>&1 < %s | \ +; RUN: FileCheck --check-prefixes=CHECK-ASM %s + +;; void f(vector float vf, ...) { +;;} + +define void @f(<4 x float> %vf, ...) #0 { +entry: + %vf.addr = alloca <4 x float>, align 16 + store <4 x float> %vf, <4 x float>* %vf.addr, align 16 + ret void +} + +;CHECK-ASM: .vbyte 4, 0x00000000 # Traceback table begin +;CHECK-ASM-NEXT: .byte 0x00 # Version = 0 +;CHECK-ASM-NEXT: .byte 0x09 # Language = CPlusPlus +;CHECK-ASM-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +;CHECK-ASM-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +;CHECK-ASM-NEXT: # -HasControlledStorage, -IsTOCless +;CHECK-ASM-NEXT: # -IsFloatingPointPresent +;CHECK-ASM-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +;CHECK-ASM-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +;CHECK-ASM-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +;CHECK-ASM-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +;CHECK-ASM-NEXT: .byte 0x80 # +HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +;CHECK-ASM-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +;CHECK-ASM-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +;CHECK-ASM-NEXT: .vbyte 4, L..f0-.f # Function size +;CHECK-ASM-NEXT: .vbyte 2, 0x0001 # Function name len = 1 +;CHECK-ASM-NEXT: .byte 102 # Function Name +;CHECK-ASM-NEXT: .byte 0x01 # NumOfVRsSaved = 0, -IsVRSavedOnStack, +HasVarArgs +;CHECK-ASM-NEXT: .byte 0x03 # NumOfVectorParams = 1, +HasVMXInstruction +;CHECK-ASM-NEXT: .vbyte 4, 0xc0000000 # Vector Parameter type = vf +;CHECK-ASM-NEXT: # -- End function diff --git a/llvm/test/CodeGen/PowerPC/aix-exception.ll b/llvm/test/CodeGen/PowerPC/aix-exception.ll --- a/llvm/test/CodeGen/PowerPC/aix-exception.ll +++ b/llvm/test/CodeGen/PowerPC/aix-exception.ll @@ -103,10 +103,10 @@ ; ASM: .vbyte 4, 0x00000000 # Traceback table begin ; ASM: .byte 0x00 # Version = 0 ; ASM: .byte 0x09 # Language = CPlusPlus -; ASM: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; ASM: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue ; ASM: # +HasTraceBackTableOffset, -IsInternalProcedure ; ASM: # -HasControlledStorage, -IsTOCless -; ASM: # +IsFloatingPointPresent +; ASM: # -IsFloatingPointPresent ; ASM: # -IsFloatingPointOperationLogOrAbortEnabled ; ASM: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed ; ASM: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved diff --git a/llvm/test/DebugInfo/XCOFF/explicit-section.ll b/llvm/test/DebugInfo/XCOFF/explicit-section.ll --- a/llvm/test/DebugInfo/XCOFF/explicit-section.ll +++ b/llvm/test/DebugInfo/XCOFF/explicit-section.ll @@ -112,10 +112,10 @@ ; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin ; CHECK-NEXT: .byte 0x00 # Version = 0 ; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus -; CHECK-NEXT: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; CHECK-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue ; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure ; CHECK-NEXT: # -HasControlledStorage, -IsTOCless -; CHECK-NEXT: # +IsFloatingPointPresent +; CHECK-NEXT: # -IsFloatingPointPresent ; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled ; CHECK-NEXT: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed ; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved diff --git a/llvm/unittests/Object/XCOFFObjectFileTest.cpp b/llvm/unittests/Object/XCOFFObjectFileTest.cpp --- a/llvm/unittests/Object/XCOFFObjectFileTest.cpp +++ b/llvm/unittests/Object/XCOFFObjectFileTest.cpp @@ -141,6 +141,20 @@ XCOFFTracebackTable TT3 = *TTOrErr3; ASSERT_TRUE(TT3.getParmsType()); EXPECT_EQ(TT3.getParmsType().getValue(), "d, i, f, f"); + + V[6] = 0x04; + V[7] = 0x1E; + V[8] = 0xAC; + V[9] = 0xAA; + V[10] = 0xAA; + V[11] = 0xAA; + Size = sizeof(V); + Expected TTOrErr4 = XCOFFTracebackTable::create(V, Size); + ASSERT_THAT_EXPECTED(TTOrErr4, Succeeded()); + XCOFFTracebackTable TT4 = *TTOrErr4; + ASSERT_TRUE(TT4.getParmsType()); + EXPECT_EQ(TT4.getParmsType().getValue(), + "f, f, d, i, i, f, f, f, f, f, f, f, f, f, f, f, f, ..."); } const uint8_t TBTableData[] = { @@ -205,7 +219,7 @@ EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u); EXPECT_TRUE(VecExt.hasVMXInstruction()); - EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vf, vf"); + EXPECT_EQ(VecExt.getVectorParmsInfo(), "vf, vf"); ASSERT_TRUE(TT.getExtensionTable()); EXPECT_EQ(TT.getExtensionTable().getValue(), @@ -216,7 +230,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) { const uint8_t TBTableData[] = { - 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; @@ -227,7 +241,7 @@ XCOFFTracebackTable TT = *TTOrErr; ASSERT_TRUE(TT.getParmsType()); - EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i"); + EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i, v, v"); ASSERT_TRUE(TT.getVectorExt()); TBVectorExt VecExt = TT.getVectorExt().getValue(); @@ -239,7 +253,7 @@ EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u); EXPECT_TRUE(VecExt.hasVMXInstruction()); - EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vi, vs, vc"); + EXPECT_EQ(VecExt.getVectorParmsInfo(), "vi, vs, vc"); ASSERT_TRUE(TT.getExtensionTable()); EXPECT_EQ(TT.getExtensionTable().getValue(), @@ -384,3 +398,49 @@ "unexpected end of data at offset 0x2c while reading [0x2c, 0x2d)")); EXPECT_EQ(Size, 44u); } + +TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterType) { + const uint8_t TBTableData[] = {0x00, 0x00, 0x22, 0x40, 0x80, 0x00, 0x01, + 0x05, 0x58, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x07, 0x61, 0x64, 0x64, + 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00}; + uint64_t Size = 28; + Expected TTOrErr = + XCOFFTracebackTable::create(TBTableData, Size); + + EXPECT_THAT_ERROR( + TTOrErr.takeError(), + FailedWithMessage("ParmsType encodes can not map to ParmsNum parameters " + "in parseParmsType.")); +} + +TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterTypeWithVecInfo) { + const uint8_t TBTableData[] = { + 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00, + 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, + 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; + uint64_t Size = 44; + Expected TTOrErr = + XCOFFTracebackTable::create(TBTableData, Size); + + EXPECT_THAT_ERROR( + TTOrErr.takeError(), + FailedWithMessage("ParmsType encodes can not map to ParmsNum parameters " + "in parseParmsTypeWithVecInfo.")); +} + +TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtVecParameterType) { + const uint8_t TBTableData[] = { + 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00, + 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, + 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00}; + uint64_t Size = 44; + Expected TTOrErr = + XCOFFTracebackTable::create(TBTableData, Size); + + EXPECT_THAT_ERROR(TTOrErr.takeError(), + FailedWithMessage("ParmsType encodes more than ParmsNum " + "parameters in parseVectorParmsType.")); +}