1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[AIX][XCOFF] emit vector info of traceback table.

Summary:

emit vector info of traceback table.

Reviewers: Jason Liu,Hubert Tong
Differential Revision: https://reviews.llvm.org/D93659
This commit is contained in:
zhijian 2021-06-14 11:15:22 -04:00
parent bc6a656349
commit ad7e1ecf68
16 changed files with 737 additions and 176 deletions

View File

@ -19,6 +19,7 @@
namespace llvm { namespace llvm {
class StringRef; class StringRef;
template <unsigned> class SmallString; template <unsigned> class SmallString;
template <typename T> class Expected;
namespace XCOFF { namespace XCOFF {
@ -286,7 +287,14 @@ enum SymbolAuxType : uint8_t {
StringRef getMappingClassString(XCOFF::StorageMappingClass SMC); StringRef getMappingClassString(XCOFF::StorageMappingClass SMC);
StringRef getRelocationTypeString(XCOFF::RelocationType Type); StringRef getRelocationTypeString(XCOFF::RelocationType Type);
SmallString<32> parseParmsType(uint32_t Value, unsigned ParmsNum); Expected<SmallString<32>> parseParmsType(uint32_t Value, unsigned FixedParmsNum,
unsigned FloatingParmsNum);
Expected<SmallString<32>> parseParmsTypeWithVecInfo(uint32_t Value,
unsigned FixedParmsNum,
unsigned FloatingParmsNum,
unsigned VectorParmsNum);
Expected<SmallString<32>> parseVectorParmsType(uint32_t Value,
unsigned ParmsNum);
struct TracebackTable { struct TracebackTable {
enum LanguageID : uint8_t { enum LanguageID : uint8_t {
@ -381,6 +389,8 @@ struct TracebackTable {
static constexpr uint32_t ParmTypeIsVectorShortBit = 0x4000'0000; static constexpr uint32_t ParmTypeIsVectorShortBit = 0x4000'0000;
static constexpr uint32_t ParmTypeIsVectorIntBit = 0x8000'0000; static constexpr uint32_t ParmTypeIsVectorIntBit = 0x8000'0000;
static constexpr uint32_t ParmTypeIsVectorFloatBit = 0xC000'0000; static constexpr uint32_t ParmTypeIsVectorFloatBit = 0xC000'0000;
static constexpr uint8_t WidthOfParamType = 2;
}; };
// Extended Traceback table flags. // Extended Traceback table flags.

View File

@ -857,9 +857,9 @@ public:
/// Return true if the specified register is modified or read in this /// Return true if the specified register is modified or read in this
/// function. This checks that no machine operands exist for the register or /// 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 /// any of its aliases. If SkipRegMaskTest is false, the register is
/// in the UsedPhysRegMask. /// considered used when it is set in the UsedPhysRegMask.
bool isPhysRegUsed(MCRegister PhysReg) const; bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest = false) const;
/// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used. /// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used.
/// This corresponds to the bit mask attached to register mask operands. /// This corresponds to the bit mask attached to register mask operands.

View File

@ -538,20 +538,19 @@ private:
}; };
class TBVectorExt { class TBVectorExt {
friend class XCOFFTracebackTable;
uint16_t Data; uint16_t Data;
uint32_t VecParmsInfo; SmallString<32> VecParmsInfo;
TBVectorExt(StringRef TBvectorStrRef); TBVectorExt(StringRef TBvectorStrRef, Error &Err);
public: public:
static Expected<TBVectorExt> create(StringRef TBvectorStrRef);
uint8_t getNumberOfVRSaved() const; uint8_t getNumberOfVRSaved() const;
bool isVRSavedOnStack() const; bool isVRSavedOnStack() const;
bool hasVarArgs() const; bool hasVarArgs() const;
uint8_t getNumberOfVectorParms() const; uint8_t getNumberOfVectorParms() const;
bool hasVMXInstruction() 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. /// This class provides methods to extract traceback table data from a buffer.

View File

@ -9,6 +9,8 @@
#include "llvm/BinaryFormat/XCOFF.h" #include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
using namespace llvm; using namespace llvm;
@ -76,6 +78,7 @@ StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) {
} }
return "Unknown"; return "Unknown";
} }
#undef RELOC_CASE
#define LANG_CASE(A) \ #define LANG_CASE(A) \
case XCOFF::TracebackTable::A: \ case XCOFF::TracebackTable::A: \
@ -104,15 +107,25 @@ StringRef XCOFF::getNameForTracebackTableLanguageId(
} }
#undef LANG_CASE #undef LANG_CASE
SmallString<32> XCOFF::parseParmsType(uint32_t Value, unsigned ParmsNum) { Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
unsigned FixedParmsNum,
unsigned FloatingParmsNum) {
SmallString<32> ParmsType; SmallString<32> ParmsType;
for (unsigned I = 0; I < ParmsNum; ++I) { int Bits = 0;
if (I != 0) unsigned ParsedFixedNum = 0;
unsigned ParsedFloatingNum = 0;
unsigned ParsedNum = 0;
unsigned ParmsNum = FixedParmsNum + FloatingParmsNum;
while (Bits < 32 && ParsedNum < ParmsNum) {
if (++ParsedNum > 1)
ParmsType += ", "; ParmsType += ", ";
if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) {
// Fixed parameter type. // Fixed parameter type.
ParmsType += "i"; ParmsType += "i";
++ParsedFixedNum;
Value <<= 1; Value <<= 1;
++Bits;
} else { } else {
if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0) if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0)
// Float parameter type. // Float parameter type.
@ -120,11 +133,21 @@ SmallString<32> XCOFF::parseParmsType(uint32_t Value, unsigned ParmsNum) {
else else
// Double parameter type. // Double parameter type.
ParmsType += "d"; ParmsType += "d";
++ParsedFloatingNum;
Value <<= 2; Value <<= 2;
Bits += 2;
} }
} }
assert(Value == 0u && "ParmsType encodes more than ParmsNum parameters.");
// 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.");
return ParmsType; return ParmsType;
} }
@ -153,4 +176,94 @@ SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) {
return Res; return Res;
} }
#undef RELOC_CASE Expected<SmallString<32>>
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<SmallString<32>> 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.");
return ParmsType;
}

View File

@ -582,8 +582,9 @@ bool MachineRegisterInfo::isPhysRegModified(MCRegister PhysReg,
return false; return false;
} }
bool MachineRegisterInfo::isPhysRegUsed(MCRegister PhysReg) const { bool MachineRegisterInfo::isPhysRegUsed(MCRegister PhysReg,
if (UsedPhysRegMask.test(PhysReg)) bool SkipRegMaskTest) const {
if (!SkipRegMaskTest && UsedPhysRegMask.test(PhysReg))
return true; return true;
const TargetRegisterInfo *TRI = getTargetRegisterInfo(); const TargetRegisterInfo *TRI = getTargetRegisterInfo();
for (MCRegAliasIterator AliasReg(PhysReg, TRI, true); AliasReg.isValid(); for (MCRegAliasIterator AliasReg(PhysReg, TRI, true); AliasReg.isValid();

View File

@ -900,15 +900,34 @@ bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
return support::endian::read32be(Bytes.data()) == 0; return support::endian::read32be(Bytes.data()) == 0;
} }
TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) {
const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
Data = support::endian::read16be(Ptr);
VecParmsInfo = support::endian::read32be(Ptr + 2);
}
#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
#define GETVALUEWITHMASKSHIFT(X, S) \ #define GETVALUEWITHMASKSHIFT(X, S) \
((Data & (TracebackTable::X)) >> (TracebackTable::S)) ((Data & (TracebackTable::X)) >> (TracebackTable::S))
Expected<TBVectorExt> 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<const uint8_t *>(TBvectorStrRef.data());
Data = support::endian::read16be(Ptr);
uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
unsigned ParmsNum =
GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
ErrorAsOutParameter EAO(&Err);
Expected<SmallString<32>> VecParmsTypeOrError =
parseVectorParmsType(VecParmsTypeValue, ParmsNum);
if (!VecParmsTypeOrError)
Err = VecParmsTypeOrError.takeError();
else
VecParmsInfo = VecParmsTypeOrError.get();
}
uint8_t TBVectorExt::getNumberOfVRSaved() const { uint8_t TBVectorExt::getNumberOfVRSaved() const {
return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
} }
@ -920,6 +939,7 @@ bool TBVectorExt::isVRSavedOnStack() const {
bool TBVectorExt::hasVarArgs() const { bool TBVectorExt::hasVarArgs() const {
return GETVALUEWITHMASK(HasVarArgsMask); return GETVALUEWITHMASK(HasVarArgsMask);
} }
uint8_t TBVectorExt::getNumberOfVectorParms() const { uint8_t TBVectorExt::getNumberOfVectorParms() const {
return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
NumberOfVectorParmsShift); NumberOfVectorParmsShift);
@ -931,72 +951,6 @@ bool TBVectorExt::hasVMXInstruction() const {
#undef GETVALUEWITHMASK #undef GETVALUEWITHMASK
#undef GETVALUEWITHMASKSHIFT #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> XCOFFTracebackTable::create(const uint8_t *Ptr, Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
uint64_t &Size) { uint64_t &Size) {
Error Err = Error::success(); Error Err = Error::success();
@ -1017,21 +971,13 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
// Skip 8 bytes of mandatory fields. // Skip 8 bytes of mandatory fields.
DE.getU64(Cur); DE.getU64(Cur);
// Begin to parse optional fields. unsigned FixedParmsNum = getNumberOfFixedParms();
if (Cur) { unsigned FloatingParmsNum = getNumberOfFPParms();
unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms(); uint32_t ParamsTypeValue = 0;
// As long as there are no "fixed-point" or floating-point parameters, this // Begin to parse optional fields.
// field remains not present even when hasVectorInfo gives true and if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
// indicates the presence of vector parameters. ParamsTypeValue = DE.getU32(Cur);
if (ParmNum > 0) {
uint32_t ParamsTypeValue = DE.getU32(Cur);
if (Cur)
ParmsType = hasVectorInfo()
? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum)
: parseParmsType(ParamsTypeValue, ParmNum);
}
}
if (Cur && hasTraceBackTableOffset()) if (Cur && hasTraceBackTableOffset())
TraceBackTableOffset = DE.getU32(Cur); TraceBackTableOffset = DE.getU32(Cur);
@ -1060,10 +1006,35 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
if (Cur && isAllocaUsed()) if (Cur && isAllocaUsed())
AllocaRegister = DE.getU8(Cur); AllocaRegister = DE.getU8(Cur);
unsigned VectorParmsNum = 0;
if (Cur && hasVectorInfo()) { if (Cur && hasVectorInfo()) {
StringRef VectorExtRef = DE.getBytes(Cur, 6); StringRef VectorExtRef = DE.getBytes(Cur, 6);
if (Cur) if (Cur) {
VecExt = TBVectorExt(VectorExtRef); Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
if (!TBVecExtOrErr) {
Err = TBVecExtOrErr.takeError();
return;
}
VecExt = TBVecExtOrErr.get();
VectorParmsNum = VecExt.getValue().getNumberOfVectorParms();
}
}
// As long as there is no fixed-point or floating-point parameter, this
// field remains not present even when hasVectorInfo gives true and
// indicates the presence of vector parameters.
if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
Expected<SmallString<32>> ParmsTypeOrError =
hasVectorInfo()
? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
FloatingParmsNum, VectorParmsNum)
: parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
if (!ParmsTypeOrError) {
Err = ParmsTypeOrError.takeError();
return;
}
ParmsType = ParmsTypeOrError.get();
} }
if (Cur && hasExtensionTable()) if (Cur && hasExtensionTable())
@ -1071,6 +1042,7 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
if (!Cur) if (!Cur)
Err = Cur.takeError(); Err = Cur.takeError();
Size = Cur.tell(); Size = Cur.tell();
} }

View File

@ -61,6 +61,7 @@
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h" #include "llvm/Support/CodeGen.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Process.h" #include "llvm/Support/Process.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
@ -1940,7 +1941,7 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
// Check the function uses floating-point processor instructions or not // Check the function uses floating-point processor instructions or not
for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) { for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {
if (MRI.isPhysRegUsed(Reg)) { if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask; FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;
break; break;
} }
@ -1980,7 +1981,8 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask; FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;
static_assert(XCOFF::AllocRegNo == 31, "Unexpected register usage!"); 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,
/* SkipRegMaskTest */ true))
FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask; FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;
const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs(); const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
@ -2025,6 +2027,20 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
(SecondHalfOfMandatoryField & 0xff000000) >> 24, 1); (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
// Set the 6th byte of mandatory field. // Set the 6th byte of mandatory field.
// Check whether has Vector Instruction,We only treat instructions uses vector
// register as vector instructions.
bool HasVectorInst = false;
for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)
if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
// Has VMX instruction.
HasVectorInst = true;
break;
}
if (FI->hasVectorParms() || HasVectorInst)
SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;
bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF); bool ShouldEmitEHBlock = TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF);
if (ShouldEmitEHBlock) if (ShouldEmitEHBlock)
SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask; SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;
@ -2053,9 +2069,9 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
(SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1); (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
// Set the 7th byte of mandatory field. // Set the 7th byte of mandatory field.
uint32_t NumberOfFixedPara = FI->getFixedParamNum(); uint32_t NumberOfFixedParms = FI->getFixedParmsNum();
SecondHalfOfMandatoryField |= SecondHalfOfMandatoryField |=
(NumberOfFixedPara << TracebackTable::NumberOfFixedParmsShift) & (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &
TracebackTable::NumberOfFixedParmsMask; TracebackTable::NumberOfFixedParmsMask;
GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField, GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,
NumberOfFixedParms); NumberOfFixedParms);
@ -2068,9 +2084,9 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
// Always set parameter on stack. // Always set parameter on stack.
SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask; SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;
uint32_t NumberOfFPPara = FI->getFloatingPointParamNum(); uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();
SecondHalfOfMandatoryField |= SecondHalfOfMandatoryField |=
(NumberOfFPPara << TracebackTable::NumberOfFloatingPointParmsShift) & (NumberOfFPParms << TracebackTable::NumberOfFloatingPointParmsShift) &
TracebackTable::NumberOfFloatingPointParmsMask; TracebackTable::NumberOfFloatingPointParmsMask;
GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField, GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,
@ -2083,18 +2099,25 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
// Generate the optional fields of traceback table. // Generate the optional fields of traceback table.
// Parameter type. // Parameter type.
if (NumberOfFixedPara || NumberOfFPPara) { if (NumberOfFixedParms || NumberOfFPParms) {
assert((SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) == uint32_t ParmsTypeValue = FI->getParmsType();
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));
}
Expected<SmallString<32>> 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. // Traceback table offset.
OutStreamer->AddComment("Function size"); OutStreamer->AddComment("Function size");
if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) { if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {
@ -2126,6 +2149,69 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg)); 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<PPCSubtarget>();
if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&
TM.getAIXExtendedAltivecABI()) {
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;
// 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;
if (HasVectorInst)
VRData |= TracebackTable::HasVMXInstructionMask;
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<SmallString<32>> 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));
// Padding 2 bytes.
CommentOS << "Padding";
EmitCommentAndValue(0, 2);
}
uint8_t ExtensionTableFlag = 0; uint8_t ExtensionTableFlag = 0;
if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) { if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {
if (ShouldEmitEHBlock) if (ShouldEmitEHBlock)
@ -2156,7 +2242,6 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
OutStreamer->AddComment("EHInfo Table"); OutStreamer->AddComment("EHInfo Table");
OutStreamer->emitValue(Exp, DL.getPointerSize()); OutStreamer->emitValue(Exp, DL.getPointerSize());
} }
#undef GENBOOLCOMMENT #undef GENBOOLCOMMENT
#undef GENVALUECOMMENT #undef GENVALUECOMMENT
} }

View File

@ -6954,10 +6954,38 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
if (VA.isRegLoc()) { if (VA.isRegLoc()) {
if (VA.getValVT().isScalarInteger()) if (VA.getValVT().isScalarInteger())
FuncInfo->appendParameterType(PPCFunctionInfo::FixedType); FuncInfo->appendParameterType(PPCFunctionInfo::FixedType);
else if (VA.getValVT().isFloatingPoint() && !VA.getValVT().isVector()) else if (VA.getValVT().isFloatingPoint() && !VA.getValVT().isVector()) {
FuncInfo->appendParameterType(VA.getValVT().SimpleTy == MVT::f32 switch (VA.getValVT().SimpleTy) {
? PPCFunctionInfo::ShortFloatPoint default:
: PPCFunctionInfo::LongFloatPoint); 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()) { if (Flags.isByVal() && VA.isMemLoc()) {

View File

@ -66,34 +66,122 @@ bool PPCFunctionInfo::isLiveInZExt(Register VReg) const {
} }
void PPCFunctionInfo::appendParameterType(ParamType Type) { void PPCFunctionInfo::appendParameterType(ParamType Type) {
uint32_t CopyParamType = ParameterType;
int Bits = 0;
// If it is fixed type, we only need to increase the FixedParamNum, for ParamtersType.push_back(Type);
// the bit encode of fixed type is bit of zero, we do not need to change the switch (Type) {
// ParamType. case FixedType:
if (Type == FixedType) { ++FixedParmsNum;
++FixedParamNum; return;
case ShortFloatingPoint:
case LongFloatingPoint:
++FloatingParmsNum;
return;
case VectorChar:
case VectorShort:
case VectorInt:
case VectorFloat:
++VectorParmsNum;
return; return;
} }
llvm_unreachable("Error ParamType type.");
}
++FloatingPointParamNum; uint32_t PPCFunctionInfo::getVecExtParmsType() const {
for (int I = 0; uint32_t VectExtParamInfo = 0;
I < static_cast<int>(FloatingPointParamNum + FixedParamNum - 1); ++I) { unsigned ShiftBits = 32 - XCOFF::TracebackTable::WidthOfParamType;
if (CopyParamType & XCOFF::TracebackTable::ParmTypeIsFloatingBit) { 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 (Bits > 31 || (Bits > 30 && (Elt != FixedType || hasVectorParms())))
break;
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. // '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. // '11'b => floating point long parameter.
CopyParamType <<= 2; ParamsTypeInfo <<= XCOFF::TracebackTable::WidthOfParamType;
Bits += 2; ParamsTypeInfo |=
} else { XCOFF::TracebackTable::ParmTypeIsDoubleBits >> ShiftBits;
// '0'b => fixed parameter. Bits += XCOFF::TracebackTable::WidthOfParamType;
CopyParamType <<= 1; break;
++Bits; 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."); return Bits < 32 ? ParamsTypeInfo << (32 - Bits) : ParamsTypeInfo;
if (Bits < 31)
ParameterType |= Type << (30 - Bits);
} }

View File

@ -23,12 +23,14 @@ namespace llvm {
/// PowerPC target-specific information for each MachineFunction. /// PowerPC target-specific information for each MachineFunction.
class PPCFunctionInfo : public MachineFunctionInfo { class PPCFunctionInfo : public MachineFunctionInfo {
public: public:
// The value in the ParamType are used to indicate the bitstrings used in the
// encoding format.
enum ParamType { enum ParamType {
FixedType = 0x0, FixedType,
ShortFloatPoint = 0x2, ShortFloatingPoint,
LongFloatPoint = 0x3 LongFloatingPoint,
VectorChar,
VectorShort,
VectorInt,
VectorFloat
}; };
private: private:
@ -120,19 +122,18 @@ private:
/// register for parameter passing. /// register for parameter passing.
unsigned VarArgsNumFPR = 0; unsigned VarArgsNumFPR = 0;
/// FixedParamNum - Number of fixed parameter. /// FixedParmsNum - The number of fixed parameters.
unsigned FixedParamNum = 0; unsigned FixedParmsNum = 0;
/// FloatingParamNum - Number of floating point parameter. /// FloatingParmsNum - The number of floating parameters.
unsigned FloatingPointParamNum = 0; unsigned FloatingParmsNum = 0;
/// ParamType - Encode type for every parameter /// VectorParmsNum - The number of vector parameters.
/// in the order of parameters passing in. unsigned VectorParmsNum = 0;
/// Bitstring starts from the most significant (leftmost) bit.
/// '0'b => fixed parameter. /// ParamtersType - Store all the parameter's type that are saved on
/// '10'b => floating point short parameter. /// registers.
/// '11'b => floating point long parameter. SmallVector<ParamType, 32> ParamtersType;
uint32_t ParameterType = 0;
/// CRSpillFrameIndex - FrameIndex for CR spill slot for 32-bit SVR4. /// CRSpillFrameIndex - FrameIndex for CR spill slot for 32-bit SVR4.
int CRSpillFrameIndex = 0; int CRSpillFrameIndex = 0;
@ -224,11 +225,15 @@ public:
unsigned getVarArgsNumGPR() const { return VarArgsNumGPR; } unsigned getVarArgsNumGPR() const { return VarArgsNumGPR; }
void setVarArgsNumGPR(unsigned Num) { VarArgsNumGPR = Num; } 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 VectorParmsNum != 0; }
unsigned getFloatingPointParamNum() const { return FloatingPointParamNum; } uint32_t getParmsType() const;
uint32_t getVecExtParmsType() const;
uint32_t getParameterType() const { return ParameterType; }
void appendParameterType(ParamType Type); void appendParameterType(ParamType Type);
unsigned getVarArgsNumFPR() const { return VarArgsNumFPR; } unsigned getVarArgsNumFPR() const { return VarArgsNumFPR; }

View File

@ -1,9 +1,9 @@
; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ ; 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: FileCheck --check-prefixes=CHECK-ASM,COMMON %s
; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -function-sections \ ; 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 ; RUN: FileCheck --check-prefixes=CHECK-FUNC,COMMON %s
define float @bar() #0 { define float @bar() #0 {
@ -26,6 +26,16 @@ entry:
ret float %add 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> <i32 123, i32 0, i32 0, i32 0>, <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: .vbyte 4, 0x00000000 # Traceback table begin
; COMMON-NEXT: .byte 0x00 # Version = 0 ; COMMON-NEXT: .byte 0x00 # Version = 0
; COMMON-NEXT: .byte 0x09 # Language = CPlusPlus ; COMMON-NEXT: .byte 0x09 # Language = CPlusPlus
@ -46,3 +56,28 @@ entry:
; COMMON-NEXT: .byte "bar" # Function Name ; COMMON-NEXT: .byte "bar" # Function Name
; COMMON-NEXT: .byte 0x1f # AllocaUsed ; COMMON-NEXT: .byte 0x1f # AllocaUsed
; COMMON-NEXT: # -- End function ; 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: .vbyte 2, 0x0000 # Padding
; COMMON-NEXT: # -- End function

View File

@ -0,0 +1,129 @@
; 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 <altivec.h>
;; 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> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>, <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, <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
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-NEXT: .vbyte 2, 0x0000 # Padding
; 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 =
; COMMON-NEXT: .vbyte 2, 0x0000 # Padding

View File

@ -0,0 +1,36 @@
; 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: .vbyte 2, 0x0000 # Padding
;CHECK-ASM-NEXT: # -- End function

View File

@ -103,10 +103,10 @@ eh.resume: ; preds = %catch.dispatch
; ASM: .vbyte 4, 0x00000000 # Traceback table begin ; ASM: .vbyte 4, 0x00000000 # Traceback table begin
; ASM: .byte 0x00 # Version = 0 ; ASM: .byte 0x00 # Version = 0
; ASM: .byte 0x09 # Language = CPlusPlus ; ASM: .byte 0x09 # Language = CPlusPlus
; ASM: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue ; ASM: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue
; ASM: # +HasTraceBackTableOffset, -IsInternalProcedure ; ASM: # +HasTraceBackTableOffset, -IsInternalProcedure
; ASM: # -HasControlledStorage, -IsTOCless ; ASM: # -HasControlledStorage, -IsTOCless
; ASM: # +IsFloatingPointPresent ; ASM: # -IsFloatingPointPresent
; ASM: # -IsFloatingPointOperationLogOrAbortEnabled ; ASM: # -IsFloatingPointOperationLogOrAbortEnabled
; ASM: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed ; ASM: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed
; ASM: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved ; ASM: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved

View File

@ -112,10 +112,10 @@ entry:
; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin ; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin
; CHECK-NEXT: .byte 0x00 # Version = 0 ; CHECK-NEXT: .byte 0x00 # Version = 0
; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus ; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus
; CHECK-NEXT: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue ; CHECK-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue
; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure ; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure
; CHECK-NEXT: # -HasControlledStorage, -IsTOCless ; CHECK-NEXT: # -HasControlledStorage, -IsTOCless
; CHECK-NEXT: # +IsFloatingPointPresent ; CHECK-NEXT: # -IsFloatingPointPresent
; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled ; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled
; CHECK-NEXT: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed ; CHECK-NEXT: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed
; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved ; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved

View File

@ -141,6 +141,20 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIParmsType) {
XCOFFTracebackTable TT3 = *TTOrErr3; XCOFFTracebackTable TT3 = *TTOrErr3;
ASSERT_TRUE(TT3.getParmsType()); ASSERT_TRUE(TT3.getParmsType());
EXPECT_EQ(TT3.getParmsType().getValue(), "d, i, f, f"); 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<XCOFFTracebackTable> 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[] = { const uint8_t TBTableData[] = {
@ -205,7 +219,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u); EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u);
EXPECT_TRUE(VecExt.hasVMXInstruction()); EXPECT_TRUE(VecExt.hasVMXInstruction());
EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vf, vf"); EXPECT_EQ(VecExt.getVectorParmsInfo(), "vf, vf");
ASSERT_TRUE(TT.getExtensionTable()); ASSERT_TRUE(TT.getExtensionTable());
EXPECT_EQ(TT.getExtensionTable().getValue(), EXPECT_EQ(TT.getExtensionTable().getValue(),
@ -216,7 +230,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) { TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
const uint8_t TBTableData[] = { 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, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
@ -227,7 +241,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
XCOFFTracebackTable TT = *TTOrErr; XCOFFTracebackTable TT = *TTOrErr;
ASSERT_TRUE(TT.getParmsType()); 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()); ASSERT_TRUE(TT.getVectorExt());
TBVectorExt VecExt = TT.getVectorExt().getValue(); TBVectorExt VecExt = TT.getVectorExt().getValue();
@ -239,7 +253,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u); EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u);
EXPECT_TRUE(VecExt.hasVMXInstruction()); EXPECT_TRUE(VecExt.hasVMXInstruction());
EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vi, vs, vc"); EXPECT_EQ(VecExt.getVectorParmsInfo(), "vi, vs, vc");
ASSERT_TRUE(TT.getExtensionTable()); ASSERT_TRUE(TT.getExtensionTable());
EXPECT_EQ(TT.getExtensionTable().getValue(), EXPECT_EQ(TT.getExtensionTable().getValue(),
@ -496,3 +510,49 @@ TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef64) {
ExpectErr.takeError(), ExpectErr.takeError(),
FailedWithMessage("csect symbol \".data\" contains no auxiliary entry")); FailedWithMessage("csect symbol \".data\" contains no auxiliary entry"));
} }
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<XCOFFTracebackTable> 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<XCOFFTracebackTable> 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<XCOFFTracebackTable> TTOrErr =
XCOFFTracebackTable::create(TBTableData, Size);
EXPECT_THAT_ERROR(TTOrErr.takeError(),
FailedWithMessage("ParmsType encodes more than ParmsNum "
"parameters in parseVectorParmsType."));
}