[DebugInfo] Change DIEnumerator payload type from int64_t to APInt
This allows the representation of arbitrarily large enumeration values. See https://lists.llvm.org/pipermail/llvm-dev/2017-December/119475.html for context. Reviewed By: andrewrk, aprantl, MaskRay Differential Revision: https://reviews.llvm.org/D62475
This commit is contained in:
parent
ecddafd84a
commit
aad3d578da
|
@ -255,6 +255,8 @@ class Module;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APInt readWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits);
|
||||||
|
|
||||||
const std::error_category &BitcodeErrorCategory();
|
const std::error_category &BitcodeErrorCategory();
|
||||||
enum class BitcodeError { CorruptedBitcode = 1 };
|
enum class BitcodeError { CorruptedBitcode = 1 };
|
||||||
inline std::error_code make_error_code(BitcodeError E) {
|
inline std::error_code make_error_code(BitcodeError E) {
|
||||||
|
|
|
@ -348,22 +348,26 @@ class DIEnumerator : public DINode {
|
||||||
friend class LLVMContextImpl;
|
friend class LLVMContextImpl;
|
||||||
friend class MDNode;
|
friend class MDNode;
|
||||||
|
|
||||||
int64_t Value;
|
APInt Value;
|
||||||
DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value,
|
DIEnumerator(LLVMContext &C, StorageType Storage, APInt Value,
|
||||||
bool IsUnsigned, ArrayRef<Metadata *> Ops)
|
bool IsUnsigned, ArrayRef<Metadata *> Ops)
|
||||||
: DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
|
: DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
|
||||||
Value(Value) {
|
Value(Value) {
|
||||||
SubclassData32 = IsUnsigned;
|
SubclassData32 = IsUnsigned;
|
||||||
}
|
}
|
||||||
|
DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value,
|
||||||
|
bool IsUnsigned, ArrayRef<Metadata *> Ops)
|
||||||
|
: DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned,
|
||||||
|
Ops) {}
|
||||||
~DIEnumerator() = default;
|
~DIEnumerator() = default;
|
||||||
|
|
||||||
static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
|
static DIEnumerator *getImpl(LLVMContext &Context, APInt Value,
|
||||||
bool IsUnsigned, StringRef Name,
|
bool IsUnsigned, StringRef Name,
|
||||||
StorageType Storage, bool ShouldCreate = true) {
|
StorageType Storage, bool ShouldCreate = true) {
|
||||||
return getImpl(Context, Value, IsUnsigned,
|
return getImpl(Context, Value, IsUnsigned,
|
||||||
getCanonicalMDString(Context, Name), Storage, ShouldCreate);
|
getCanonicalMDString(Context, Name), Storage, ShouldCreate);
|
||||||
}
|
}
|
||||||
static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
|
static DIEnumerator *getImpl(LLVMContext &Context, APInt Value,
|
||||||
bool IsUnsigned, MDString *Name,
|
bool IsUnsigned, MDString *Name,
|
||||||
StorageType Storage, bool ShouldCreate = true);
|
StorageType Storage, bool ShouldCreate = true);
|
||||||
|
|
||||||
|
@ -372,14 +376,22 @@ class DIEnumerator : public DINode {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name),
|
DEFINE_MDNODE_GET(DIEnumerator,
|
||||||
|
(int64_t Value, bool IsUnsigned, StringRef Name),
|
||||||
|
(APInt(64, Value, !IsUnsigned), IsUnsigned, Name))
|
||||||
|
DEFINE_MDNODE_GET(DIEnumerator,
|
||||||
|
(int64_t Value, bool IsUnsigned, MDString *Name),
|
||||||
|
(APInt(64, Value, !IsUnsigned), IsUnsigned, Name))
|
||||||
|
DEFINE_MDNODE_GET(DIEnumerator,
|
||||||
|
(APInt Value, bool IsUnsigned, StringRef Name),
|
||||||
(Value, IsUnsigned, Name))
|
(Value, IsUnsigned, Name))
|
||||||
DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name),
|
DEFINE_MDNODE_GET(DIEnumerator,
|
||||||
|
(APInt Value, bool IsUnsigned, MDString *Name),
|
||||||
(Value, IsUnsigned, Name))
|
(Value, IsUnsigned, Name))
|
||||||
|
|
||||||
TempDIEnumerator clone() const { return cloneImpl(); }
|
TempDIEnumerator clone() const { return cloneImpl(); }
|
||||||
|
|
||||||
int64_t getValue() const { return Value; }
|
const APInt &getValue() const { return Value; }
|
||||||
bool isUnsigned() const { return SubclassData32; }
|
bool isUnsigned() const { return SubclassData32; }
|
||||||
StringRef getName() const { return getStringOperand(0); }
|
StringRef getName() const { return getStringOperand(0); }
|
||||||
|
|
||||||
|
|
|
@ -3872,6 +3872,10 @@ struct DISPFlagField : public MDFieldImpl<DISubprogram::DISPFlags> {
|
||||||
DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {}
|
DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MDAPSIntField : public MDFieldImpl<APSInt> {
|
||||||
|
MDAPSIntField() : ImplTy(APSInt()) {}
|
||||||
|
};
|
||||||
|
|
||||||
struct MDSignedField : public MDFieldImpl<int64_t> {
|
struct MDSignedField : public MDFieldImpl<int64_t> {
|
||||||
int64_t Min;
|
int64_t Min;
|
||||||
int64_t Max;
|
int64_t Max;
|
||||||
|
@ -3950,6 +3954,16 @@ struct MDSignedOrUnsignedField
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDAPSIntField &Result) {
|
||||||
|
if (Lex.getKind() != lltok::APSInt)
|
||||||
|
return TokError("expected integer");
|
||||||
|
|
||||||
|
Result.assign(Lex.getAPSIntVal());
|
||||||
|
Lex.Lex();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
|
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
|
||||||
MDUnsignedField &Result) {
|
MDUnsignedField &Result) {
|
||||||
|
@ -4281,27 +4295,6 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
|
|
||||||
MDSignedOrUnsignedField &Result) {
|
|
||||||
if (Lex.getKind() != lltok::APSInt)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Lex.getAPSIntVal().isSigned()) {
|
|
||||||
MDSignedField Res = Result.A;
|
|
||||||
if (ParseMDField(Loc, Name, Res))
|
|
||||||
return true;
|
|
||||||
Result.assign(Res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MDUnsignedField Res = Result.B;
|
|
||||||
if (ParseMDField(Loc, Name, Res))
|
|
||||||
return true;
|
|
||||||
Result.assign(Res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
|
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
|
||||||
LocTy ValueLoc = Lex.getLoc();
|
LocTy ValueLoc = Lex.getLoc();
|
||||||
|
@ -4475,17 +4468,20 @@ bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) {
|
||||||
bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) {
|
bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) {
|
||||||
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
|
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
|
||||||
REQUIRED(name, MDStringField, ); \
|
REQUIRED(name, MDStringField, ); \
|
||||||
REQUIRED(value, MDSignedOrUnsignedField, ); \
|
REQUIRED(value, MDAPSIntField, ); \
|
||||||
OPTIONAL(isUnsigned, MDBoolField, (false));
|
OPTIONAL(isUnsigned, MDBoolField, (false));
|
||||||
PARSE_MD_FIELDS();
|
PARSE_MD_FIELDS();
|
||||||
#undef VISIT_MD_FIELDS
|
#undef VISIT_MD_FIELDS
|
||||||
|
|
||||||
if (isUnsigned.Val && value.isMDSignedField())
|
if (isUnsigned.Val && value.Val.isNegative())
|
||||||
return TokError("unsigned enumerator with negative value");
|
return TokError("unsigned enumerator with negative value");
|
||||||
|
|
||||||
int64_t Value = value.isMDSignedField()
|
APSInt Value(value.Val);
|
||||||
? value.getMDSignedValue()
|
// Add a leading zero so that unsigned values with the msb set are not
|
||||||
: static_cast<int64_t>(value.getMDUnsignedValue());
|
// mistaken for negative values when used for signed enumerators.
|
||||||
|
if (!isUnsigned.Val && value.Val.isUnsigned() && value.Val.isSignBitSet())
|
||||||
|
Value = Value.zext(Value.getBitWidth() + 1);
|
||||||
|
|
||||||
Result =
|
Result =
|
||||||
GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val));
|
GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val));
|
||||||
|
|
||||||
|
|
|
@ -2317,7 +2317,7 @@ Error BitcodeReader::resolveGlobalAndIndirectSymbolInits() {
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
static APInt readWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
|
APInt llvm::readWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
|
||||||
SmallVector<uint64_t, 8> Words(Vals.size());
|
SmallVector<uint64_t, 8> Words(Vals.size());
|
||||||
transform(Vals, Words.begin(),
|
transform(Vals, Words.begin(),
|
||||||
BitcodeReader::decodeSignRotatedValue);
|
BitcodeReader::decodeSignRotatedValue);
|
||||||
|
|
|
@ -1277,14 +1277,24 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case bitc::METADATA_ENUMERATOR: {
|
case bitc::METADATA_ENUMERATOR: {
|
||||||
if (Record.size() != 3)
|
if (Record.size() < 3)
|
||||||
return error("Invalid record");
|
return error("Invalid record");
|
||||||
|
|
||||||
IsDistinct = Record[0] & 1;
|
IsDistinct = Record[0] & 1;
|
||||||
bool IsUnsigned = Record[0] & 2;
|
bool IsUnsigned = Record[0] & 2;
|
||||||
|
bool IsBigInt = Record[0] & 4;
|
||||||
|
APInt Value;
|
||||||
|
|
||||||
|
if (IsBigInt) {
|
||||||
|
const uint64_t BitWidth = Record[1];
|
||||||
|
const size_t NumWords = Record.size() - 3;
|
||||||
|
Value = readWideAPInt(makeArrayRef(&Record[3], NumWords), BitWidth);
|
||||||
|
} else
|
||||||
|
Value = APInt(64, unrotateSign(Record[1]), !IsUnsigned);
|
||||||
|
|
||||||
MetadataList.assignValue(
|
MetadataList.assignValue(
|
||||||
GET_OR_DISTINCT(DIEnumerator, (Context, unrotateSign(Record[1]),
|
GET_OR_DISTINCT(DIEnumerator,
|
||||||
IsUnsigned, getMDString(Record[2]))),
|
(Context, Value, IsUnsigned, getMDString(Record[2]))),
|
||||||
NextMetadataNo);
|
NextMetadataNo);
|
||||||
NextMetadataNo++;
|
NextMetadataNo++;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1529,12 +1529,32 @@ void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N,
|
||||||
Record.clear();
|
Record.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) {
|
||||||
|
if ((int64_t)V >= 0)
|
||||||
|
Vals.push_back(V << 1);
|
||||||
|
else
|
||||||
|
Vals.push_back((-V << 1) | 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emitWideAPInt(SmallVectorImpl<uint64_t> &Vals, const APInt &A) {
|
||||||
|
// We have an arbitrary precision integer value to write whose
|
||||||
|
// bit width is > 64. However, in canonical unsigned integer
|
||||||
|
// format it is likely that the high bits are going to be zero.
|
||||||
|
// So, we only write the number of active words.
|
||||||
|
unsigned NumWords = A.getActiveWords();
|
||||||
|
const uint64_t *RawData = A.getRawData();
|
||||||
|
for (unsigned i = 0; i < NumWords; i++)
|
||||||
|
emitSignedInt64(Vals, RawData[i]);
|
||||||
|
}
|
||||||
|
|
||||||
void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N,
|
void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N,
|
||||||
SmallVectorImpl<uint64_t> &Record,
|
SmallVectorImpl<uint64_t> &Record,
|
||||||
unsigned Abbrev) {
|
unsigned Abbrev) {
|
||||||
Record.push_back((N->isUnsigned() << 1) | N->isDistinct());
|
const uint64_t IsBigInt = 1 << 2;
|
||||||
Record.push_back(rotateSign(N->getValue()));
|
Record.push_back(IsBigInt | (N->isUnsigned() << 1) | N->isDistinct());
|
||||||
|
Record.push_back(N->getValue().getBitWidth());
|
||||||
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
|
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
|
||||||
|
emitWideAPInt(Record, N->getValue());
|
||||||
|
|
||||||
Stream.EmitRecord(bitc::METADATA_ENUMERATOR, Record, Abbrev);
|
Stream.EmitRecord(bitc::METADATA_ENUMERATOR, Record, Abbrev);
|
||||||
Record.clear();
|
Record.clear();
|
||||||
|
@ -2269,13 +2289,6 @@ void ModuleBitcodeWriter::writeSyncScopeNames() {
|
||||||
Stream.ExitBlock();
|
Stream.ExitBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) {
|
|
||||||
if ((int64_t)V >= 0)
|
|
||||||
Vals.push_back(V << 1);
|
|
||||||
else
|
|
||||||
Vals.push_back((-V << 1) | 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
||||||
bool isGlobal) {
|
bool isGlobal) {
|
||||||
if (FirstVal == LastVal) return;
|
if (FirstVal == LastVal) return;
|
||||||
|
@ -2362,15 +2375,7 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
||||||
Code = bitc::CST_CODE_INTEGER;
|
Code = bitc::CST_CODE_INTEGER;
|
||||||
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
|
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
|
||||||
} else { // Wide integers, > 64 bits in size.
|
} else { // Wide integers, > 64 bits in size.
|
||||||
// We have an arbitrary precision integer value to write whose
|
emitWideAPInt(Record, IV->getValue());
|
||||||
// bit width is > 64. However, in canonical unsigned integer
|
|
||||||
// format it is likely that the high bits are going to be zero.
|
|
||||||
// So, we only write the number of active words.
|
|
||||||
unsigned NWords = IV->getValue().getActiveWords();
|
|
||||||
const uint64_t *RawWords = IV->getValue().getRawData();
|
|
||||||
for (unsigned i = 0; i != NWords; ++i) {
|
|
||||||
emitSignedInt64(Record, RawWords[i]);
|
|
||||||
}
|
|
||||||
Code = bitc::CST_CODE_WIDE_INTEGER;
|
Code = bitc::CST_CODE_WIDE_INTEGER;
|
||||||
}
|
}
|
||||||
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
||||||
|
|
|
@ -2080,7 +2080,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
|
||||||
// order, which is what MSVC does.
|
// order, which is what MSVC does.
|
||||||
if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
|
if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
|
||||||
EnumeratorRecord ER(MemberAccess::Public,
|
EnumeratorRecord ER(MemberAccess::Public,
|
||||||
APSInt::getUnsigned(Enumerator->getValue()),
|
APSInt(Enumerator->getValue(), true),
|
||||||
Enumerator->getName());
|
Enumerator->getName());
|
||||||
ContinuationBuilder.writeMemberType(ER);
|
ContinuationBuilder.writeMemberType(ER);
|
||||||
EnumeratorCount++;
|
EnumeratorCount++;
|
||||||
|
|
|
@ -1449,8 +1449,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
|
||||||
DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
|
DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
|
||||||
StringRef Name = Enum->getName();
|
StringRef Name = Enum->getName();
|
||||||
addString(Enumerator, dwarf::DW_AT_name, Name);
|
addString(Enumerator, dwarf::DW_AT_name, Name);
|
||||||
auto Value = static_cast<uint64_t>(Enum->getValue());
|
addConstantValue(Enumerator, Enum->getValue(), IsUnsigned);
|
||||||
addConstantValue(Enumerator, IsUnsigned, Value);
|
|
||||||
if (IndexEnumerators)
|
if (IndexEnumerators)
|
||||||
addGlobalName(Name, Enumerator, Context);
|
addGlobalName(Name, Enumerator, Context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1647,6 +1647,8 @@ struct MDFieldPrinter {
|
||||||
bool ShouldSkipNull = true);
|
bool ShouldSkipNull = true);
|
||||||
template <class IntTy>
|
template <class IntTy>
|
||||||
void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true);
|
void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true);
|
||||||
|
void printAPInt(StringRef Name, APInt Int, bool IsUnsigned,
|
||||||
|
bool ShouldSkipZero);
|
||||||
void printBool(StringRef Name, bool Value, Optional<bool> Default = None);
|
void printBool(StringRef Name, bool Value, Optional<bool> Default = None);
|
||||||
void printDIFlags(StringRef Name, DINode::DIFlags Flags);
|
void printDIFlags(StringRef Name, DINode::DIFlags Flags);
|
||||||
void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags);
|
void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags);
|
||||||
|
@ -1722,6 +1724,15 @@ void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) {
|
||||||
Out << FS << Name << ": " << Int;
|
Out << FS << Name << ": " << Int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MDFieldPrinter::printAPInt(StringRef Name, APInt Int, bool IsUnsigned,
|
||||||
|
bool ShouldSkipZero) {
|
||||||
|
if (ShouldSkipZero && Int.isNullValue())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Out << FS << Name << ": ";
|
||||||
|
Int.print(Out, !IsUnsigned);
|
||||||
|
}
|
||||||
|
|
||||||
void MDFieldPrinter::printBool(StringRef Name, bool Value,
|
void MDFieldPrinter::printBool(StringRef Name, bool Value,
|
||||||
Optional<bool> Default) {
|
Optional<bool> Default) {
|
||||||
if (Default && Value == *Default)
|
if (Default && Value == *Default)
|
||||||
|
@ -1851,13 +1862,10 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
|
||||||
Out << "!DIEnumerator(";
|
Out << "!DIEnumerator(";
|
||||||
MDFieldPrinter Printer(Out);
|
MDFieldPrinter Printer(Out);
|
||||||
Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
|
Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
|
||||||
if (N->isUnsigned()) {
|
Printer.printAPInt("value", N->getValue(), N->isUnsigned(),
|
||||||
auto Value = static_cast<uint64_t>(N->getValue());
|
/*ShouldSkipZero=*/false);
|
||||||
Printer.printInt("value", Value, /* ShouldSkipZero */ false);
|
if (N->isUnsigned())
|
||||||
Printer.printBool("isUnsigned", true);
|
Printer.printBool("isUnsigned", true);
|
||||||
} else {
|
|
||||||
Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false);
|
|
||||||
}
|
|
||||||
Out << ")";
|
Out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,8 @@ DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent,
|
||||||
DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val,
|
DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val,
|
||||||
bool IsUnsigned) {
|
bool IsUnsigned) {
|
||||||
assert(!Name.empty() && "Unable to create enumerator without name");
|
assert(!Name.empty() && "Unable to create enumerator without name");
|
||||||
return DIEnumerator::get(VMContext, Val, IsUnsigned, Name);
|
return DIEnumerator::get(VMContext, APInt(64, Val, !IsUnsigned), IsUnsigned,
|
||||||
|
Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) {
|
DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) {
|
||||||
|
|
|
@ -347,7 +347,7 @@ DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
|
||||||
DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops);
|
DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value,
|
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, APInt Value,
|
||||||
bool IsUnsigned, MDString *Name,
|
bool IsUnsigned, MDString *Name,
|
||||||
StorageType Storage, bool ShouldCreate) {
|
StorageType Storage, bool ShouldCreate) {
|
||||||
assert(isCanonical(Name) && "Expected canonical MDString");
|
assert(isCanonical(Name) && "Expected canonical MDString");
|
||||||
|
|
|
@ -355,19 +355,22 @@ template <> struct MDNodeKeyImpl<DISubrange> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct MDNodeKeyImpl<DIEnumerator> {
|
template <> struct MDNodeKeyImpl<DIEnumerator> {
|
||||||
int64_t Value;
|
APInt Value;
|
||||||
MDString *Name;
|
MDString *Name;
|
||||||
bool IsUnsigned;
|
bool IsUnsigned;
|
||||||
|
|
||||||
MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
|
MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name)
|
||||||
: Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
|
: Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
|
||||||
|
MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
|
||||||
|
: Value(APInt(64, Value, !IsUnsigned)), Name(Name),
|
||||||
|
IsUnsigned(IsUnsigned) {}
|
||||||
MDNodeKeyImpl(const DIEnumerator *N)
|
MDNodeKeyImpl(const DIEnumerator *N)
|
||||||
: Value(N->getValue()), Name(N->getRawName()),
|
: Value(N->getValue()), Name(N->getRawName()),
|
||||||
IsUnsigned(N->isUnsigned()) {}
|
IsUnsigned(N->isUnsigned()) {}
|
||||||
|
|
||||||
bool isKeyOf(const DIEnumerator *RHS) const {
|
bool isKeyOf(const DIEnumerator *RHS) const {
|
||||||
return Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() &&
|
return APInt::isSameValue(Value, RHS->getValue()) &&
|
||||||
Name == RHS->getRawName();
|
IsUnsigned == RHS->isUnsigned() && Name == RHS->getRawName();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getHashValue() const { return hash_combine(Value, Name); }
|
unsigned getHashValue() const { return hash_combine(Value, Name); }
|
||||||
|
|
|
@ -171,7 +171,12 @@ void BTFTypeEnum::completeType(BTFDebug &BDebug) {
|
||||||
struct BTF::BTFEnum BTFEnum;
|
struct BTF::BTFEnum BTFEnum;
|
||||||
BTFEnum.NameOff = BDebug.addString(Enum->getName());
|
BTFEnum.NameOff = BDebug.addString(Enum->getName());
|
||||||
// BTF enum value is 32bit, enforce it.
|
// BTF enum value is 32bit, enforce it.
|
||||||
BTFEnum.Val = static_cast<uint32_t>(Enum->getValue());
|
uint32_t Value;
|
||||||
|
if (Enum->isUnsigned())
|
||||||
|
Value = static_cast<uint32_t>(Enum->getValue().getZExtValue());
|
||||||
|
else
|
||||||
|
Value = static_cast<uint32_t>(Enum->getValue().getSExtValue());
|
||||||
|
BTFEnum.Val = Value;
|
||||||
EnumValues.push_back(BTFEnum);
|
EnumValues.push_back(BTFEnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
;; Round-trip test for enumeration members using more than 64 bits.
|
||||||
|
|
||||||
|
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
|
||||||
|
|
||||||
|
!named = !{!0, !1, !2}
|
||||||
|
|
||||||
|
; CHECK: !DIEnumerator(name: "D0", value: -170141183460469231731687303715884105728)
|
||||||
|
; CHECK: !DIEnumerator(name: "D1", value: 170141183460469231731687303715884105727)
|
||||||
|
!0 = !DIEnumerator(name: "D0", value: -170141183460469231731687303715884105728)
|
||||||
|
!1 = !DIEnumerator(name: "D1", value: 170141183460469231731687303715884105727)
|
||||||
|
|
||||||
|
; CHECK: !DIEnumerator(name: "D1", value: 2722258935367507707706996859454145691648, isUnsigned: true)
|
||||||
|
!2 = !DIEnumerator(name: "D1", value: 2722258935367507707706996859454145691648, isUnsigned: true)
|
|
@ -0,0 +1,10 @@
|
||||||
|
;; DIEnumerator-10.0.ll.bc was generated by llvm-as 10.0.0
|
||||||
|
; RUN: llvm-dis < %s.bc | FileCheck %s
|
||||||
|
; RUN: verify-uselistorder < %s.bc
|
||||||
|
|
||||||
|
!named = !{!0, !1}
|
||||||
|
|
||||||
|
; CHECK: !DIEnumerator(name: "A0", value: 9223372036854775807)
|
||||||
|
!0 = !DIEnumerator(name: "A0", value: 9223372036854775807)
|
||||||
|
; CHECK: !DIEnumerator(name: "B0", value: -9223372036854775808)
|
||||||
|
!1 = !DIEnumerator(name: "B0", value: -9223372036854775808)
|
Binary file not shown.
|
@ -1186,7 +1186,7 @@ typedef MetadataTest DIEnumeratorTest;
|
||||||
TEST_F(DIEnumeratorTest, get) {
|
TEST_F(DIEnumeratorTest, get) {
|
||||||
auto *N = DIEnumerator::get(Context, 7, false, "name");
|
auto *N = DIEnumerator::get(Context, 7, false, "name");
|
||||||
EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());
|
EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());
|
||||||
EXPECT_EQ(7, N->getValue());
|
EXPECT_EQ(7, N->getValue().getSExtValue());
|
||||||
EXPECT_FALSE(N->isUnsigned());
|
EXPECT_FALSE(N->isUnsigned());
|
||||||
EXPECT_EQ("name", N->getName());
|
EXPECT_EQ("name", N->getName());
|
||||||
EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name"));
|
EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name"));
|
||||||
|
@ -1199,6 +1199,15 @@ TEST_F(DIEnumeratorTest, get) {
|
||||||
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
|
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DIEnumeratorTest, getWithLargeValues) {
|
||||||
|
auto *N = DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val");
|
||||||
|
EXPECT_EQ(128U, N->getValue().countPopulation());
|
||||||
|
EXPECT_EQ(N,
|
||||||
|
DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val"));
|
||||||
|
EXPECT_NE(N,
|
||||||
|
DIEnumerator::get(Context, APInt::getMinValue(128), false, "val"));
|
||||||
|
}
|
||||||
|
|
||||||
typedef MetadataTest DIBasicTypeTest;
|
typedef MetadataTest DIBasicTypeTest;
|
||||||
|
|
||||||
TEST_F(DIBasicTypeTest, get) {
|
TEST_F(DIBasicTypeTest, get) {
|
||||||
|
|
Loading…
Reference in New Issue