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/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -399,17 +399,18 @@ 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."); + else + 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/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -845,15 +845,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); } @@ -865,6 +884,7 @@ bool TBVectorExt::hasVarArgs() const { return GETVALUEWITHMASK(HasVarArgsMask); } + uint8_t TBVectorExt::getNumberOfVectorParms() const { return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); @@ -876,72 +896,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(); @@ -954,7 +908,6 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err) : TBPtr(Ptr) { - ErrorAsOutParameter EAO(&Err); DataExtractor DE(ArrayRef(Ptr, Size), /*IsLittleEndian=*/false, /*AddressSize=*/0); DataExtractor::Cursor Cur(/*Offset=*/0); @@ -962,20 +915,14 @@ // 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 (FixedParmsNum + FloatingParmsNum > 0) + ParamsTypeValue = DE.getU32(Cur); } if (Cur && hasTraceBackTableOffset()) @@ -1005,17 +952,46 @@ 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) { + ErrorAsOutParameter EAO(&Err); + 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) { + ErrorAsOutParameter EAO(&Err); + Err = ParmsTypeOrError.takeError(); + return; + } + ParmsType = ParmsTypeOrError.get(); } if (Cur && hasExtensionTable()) ExtensionTable = DE.getU8(Cur); - if (!Cur) + if (!Cur) { + ErrorAsOutParameter EAO(&Err); 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" @@ -1881,6 +1882,9 @@ (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1); // Set the 6th byte of mandatory field. + if (FI->hasVectorInfo()) + SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask; + bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF); if (ShouldEmitEHBlock) SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask; @@ -1909,9 +1913,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); @@ -1924,9 +1928,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, @@ -1939,18 +1943,24 @@ // 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); + if (NumberOfFixedParms || NumberOfFPParms) { + uint32_t ParmsTypeValue = FI->getParmsType(); + + Expected> ParmsType = + FI->hasVectorInfo() + ? XCOFF::parseParmsTypeWithVecInfo( + ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms, + FI->getVectorParmsNum()) + : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms, + NumberOfFPParms); + + assert(ParmsType && toString(ParmsType.takeError()).c_str()); + + CommentOS << "Parameter type = " << ParmsType.get(); EmitComment(); - OutStreamer->emitIntValueInHexWithPadding(ParaType, sizeof(ParaType)); + OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue, + sizeof(ParmsTypeValue)); } - // Traceback table offset. OutStreamer->AddComment("Function size"); if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) { @@ -1982,6 +1992,61 @@ OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg)); } + if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) { + uint16_t VRData = 0; + // Calculate the number of VRs be saved. + for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg) + if (MRI.isPhysRegModified(Reg)) { + // Number of VRs saved. + VRData |= + ((PPC::V31 - Reg + 1) << TracebackTable::NumberOfVRSavedShift) & + TracebackTable::NumberOfVRSavedMask; + + // VR is saved on the stack. + VRData |= TracebackTable::IsVRSavedOnStackMask; + break; + } + + // Set has_varargs. + if (FI->getVarArgsStackOffset()) + 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.isPhysRegUsed(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) @@ -2009,7 +2074,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 @@ -7338,10 +7338,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: @@ -117,19 +119,11 @@ /// register for parameter passing. unsigned VarArgsNumFPR = 0; - /// FixedParamNum - Number of fixed parameter. - unsigned FixedParamNum = 0; + /// HasVectorInfo - True if ther are vector parameters + bool HasVectorInfo = false; - /// FloatingParamNum - Number of floating point parameter. - unsigned FloatingPointParamNum = 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; + /// ParamTypes - Store all the paramters type. + SmallVector ParamtersType; /// CRSpillFrameIndex - FrameIndex for CR spill slot for 32-bit SVR4. int CRSpillFrameIndex = 0; @@ -214,11 +208,17 @@ unsigned getVarArgsNumGPR() const { return VarArgsNumGPR; } void setVarArgsNumGPR(unsigned Num) { VarArgsNumGPR = Num; } - unsigned getFixedParamNum() const { return FixedParamNum; } + unsigned getFixedParmsNum() const; + + unsigned getFloatingPointParmsNum() const; + unsigned getVectorParmsNum() const; + + bool hasVectorInfo() const { return HasVectorInfo; } + + 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 @@ -65,35 +65,133 @@ return false; } +unsigned PPCFunctionInfo::getFixedParmsNum() const { + unsigned Num = 0; + for (const auto &Elt : ParamtersType) + if (Elt == FixedType) + ++Num; + return Num; +} + +unsigned PPCFunctionInfo::getFloatingPointParmsNum() const { + unsigned Num = 0; + for (const auto &Elt : ParamtersType) + if (Elt >= ShortFloatingPoint && Elt <= LongFloatingPoint) + ++Num; + return Num; +} + +unsigned PPCFunctionInfo::getVectorParmsNum() const { + unsigned Num = 0; + for (const auto &Elt : ParamtersType) + if (Elt >= VectorChar && Elt <= VectorFloat) + ++Num; + return Num; +} + void PPCFunctionInfo::appendParameterType(ParamType Type) { - uint32_t CopyParamType = ParameterType; + if (!HasVectorInfo && (Type >= VectorChar && Type <= VectorFloat)) + HasVectorInfo = true; + + ParamtersType.push_back(Type); +} + +uint32_t PPCFunctionInfo::getVecExtParmsType() const { + assert(HasVectorInfo && "There is not vector paramter in the function."); + uint32_t VectExtParamInfo = 0; + unsigned ShiftBits = 32 - XCOFF::TracebackTable::WidthOfParamType; int Bits = 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; + } - // 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; - return; + // 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) { - ++FloatingPointParamNum; + if (Elt == FixedType && !HasVectorInfo && Bits > 31) + break; + if ((Elt != FixedType || HasVectorInfo) && Bits > 30) + break; - for (int I = 0; - I < static_cast(FloatingPointParamNum + FixedParamNum - 1); ++I) { - if (CopyParamType & XCOFF::TracebackTable::ParmTypeIsFloatingBit) { + switch (Elt) { + case FixedType: + if (HasVectorInfo) { + //'00' ==> fixed parameter if HasVectorInfo is true. + ParamsTypeInfo <<= XCOFF::TracebackTable::WidthOfParamType; + ParamsTypeInfo |= + XCOFF::TracebackTable::ParmTypeIsFixedBits >> ShiftBits; + Bits += XCOFF::TracebackTable::WidthOfParamType; + } else { + //'0' ==> fixed parameter if HasVectorInfo 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; + default: + assert(false && "Unrecognized type in ParamtersType"); } } - 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-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,58 @@ +; 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 + +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 +} + +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 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.")); +}