-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Add the 'initializes' attribute langref and support #84803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 34 commits
2554c82
a9256bf
9150ece
206b707
eaf5ca0
52cc649
f7fddb0
3b5955a
6a1df7a
fe2e0a5
f73df04
63c45f6
dcc2b38
9723322
e70988d
9782c31
a924dd3
45cdc34
4eeba08
502e062
fac03b8
ea3e7c5
7630510
a604b4f
f941b24
e52fd9d
8e64fa9
9ae0fca
d4809ab
99d36cc
96191cd
645f577
2a8ea9a
37edecd
80306d7
67445fe
68643a5
46e8d87
714d02f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ class AttributeImpl; | |
class AttributeListImpl; | ||
class AttributeSetNode; | ||
class ConstantRange; | ||
class ConstantRangeList; | ||
class FoldingSetNodeID; | ||
class Function; | ||
class LLVMContext; | ||
|
@@ -107,6 +108,10 @@ class Attribute { | |
static bool isConstantRangeAttrKind(AttrKind Kind) { | ||
return Kind >= FirstConstantRangeAttr && Kind <= LastConstantRangeAttr; | ||
} | ||
static bool isConstantRangeListAttrKind(AttrKind Kind) { | ||
return Kind >= FirstConstantRangeListAttr && | ||
Kind <= LastConstantRangeListAttr; | ||
} | ||
|
||
static bool canUseAsFnAttr(AttrKind Kind); | ||
static bool canUseAsParamAttr(AttrKind Kind); | ||
|
@@ -131,6 +136,8 @@ class Attribute { | |
static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty); | ||
static Attribute get(LLVMContext &Context, AttrKind Kind, | ||
const ConstantRange &CR); | ||
static Attribute get(LLVMContext &Context, AttrKind Kind, | ||
const ConstantRangeList &CRL); | ||
|
||
/// Return a uniquified Attribute object that has the specific | ||
/// alignment set. | ||
|
@@ -189,6 +196,9 @@ class Attribute { | |
/// Return true if the attribute is a ConstantRange attribute. | ||
bool isConstantRangeAttribute() const; | ||
|
||
/// Return true if the attribute is a ConstantRangeList attribute. | ||
bool isConstantRangeListAttribute() const; | ||
|
||
/// Return true if the attribute is any kind of attribute. | ||
bool isValid() const { return pImpl; } | ||
|
||
|
@@ -226,6 +236,10 @@ class Attribute { | |
/// attribute to be a ConstantRange attribute. | ||
const ConstantRange &getValueAsConstantRange() const; | ||
|
||
/// Return the attribute's value as a ConstantRangeList. This requires the | ||
/// attribute to be a ConstantRangeList attribute. | ||
ConstantRangeList getValueAsConstantRangeList() const; | ||
|
||
/// Returns the alignment field of an attribute as a byte alignment | ||
/// value. | ||
MaybeAlign getAlignment() const; | ||
|
@@ -267,6 +281,9 @@ class Attribute { | |
/// Returns the value of the range attribute. | ||
const ConstantRange &getRange() const; | ||
|
||
/// Returns the value of the initializes attribute. | ||
ConstantRangeList getInitializes() const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Perhaps return ArrayRef to be consistent with getValueAsConstantRangeList(), then the caller can decide to make it a ConstantRangeList or not? Also ArrayRef allows the caller to avoid a copy if it isn't needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||
|
||
/// The Attribute is converted to a string of equivalent mnemonic. This | ||
/// is, presumably, for writing out the mnemonics for the assembly writer. | ||
std::string getAsString(bool InAttrGrp = false) const; | ||
|
@@ -1222,6 +1239,13 @@ class AttrBuilder { | |
/// Add range attribute. | ||
AttrBuilder &addRangeAttr(const ConstantRange &CR); | ||
|
||
/// Add a ConstantRangeList attribute with the given ranges. | ||
AttrBuilder &addConstantRangeListAttr(Attribute::AttrKind Kind, | ||
const ConstantRangeList &CRL); | ||
|
||
/// Add initializes attribute. | ||
AttrBuilder &addInitializesAttr(const ConstantRangeList &CRL); | ||
|
||
ArrayRef<Attribute> attrs() const { return Attrs; } | ||
|
||
bool operator==(const AttrBuilder &B) const; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
//===- ConstantRangeList.h - A list of constant ranges ----------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Represent a list of signed ConstantRange and do NOT support wrap around the | ||
// end of the numeric range. Ranges in the list are ordered and not overlapping. | ||
// Ranges should have the same bitwidth. Each range's lower should be less than | ||
// its upper. | ||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_IR_CONSTANTRANGELIST_H | ||
#define LLVM_IR_CONSTANTRANGELIST_H | ||
|
||
#include "llvm/ADT/APInt.h" | ||
#include "llvm/IR/ConstantRange.h" | ||
#include "llvm/Support/Debug.h" | ||
#include <cstddef> | ||
#include <cstdint> | ||
|
||
namespace llvm { | ||
|
||
class raw_ostream; | ||
|
||
/// This class represents a list of constant ranges. | ||
class [[nodiscard]] ConstantRangeList { | ||
SmallVector<ConstantRange, 2> Ranges; | ||
|
||
public: | ||
ConstantRangeList() = default; | ||
ConstantRangeList(ArrayRef<ConstantRange> RangesRef) { | ||
assert(isOrderedRanges(RangesRef)); | ||
for (const ConstantRange &R : RangesRef) { | ||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
assert(R.getBitWidth() == getBitWidth()); | ||
Ranges.push_back(R); | ||
} | ||
} | ||
|
||
// Return true if the ranges are non-overlapping and increasing. | ||
static bool isOrderedRanges(ArrayRef<ConstantRange> RangesRef); | ||
static std::optional<ConstantRangeList> | ||
getConstantRangeList(ArrayRef<ConstantRange> RangesRef); | ||
|
||
SmallVectorImpl<ConstantRange>::iterator begin() { return Ranges.begin(); } | ||
aeubanks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
SmallVectorImpl<ConstantRange>::iterator end() { return Ranges.end(); } | ||
SmallVectorImpl<ConstantRange>::const_iterator begin() const { | ||
return Ranges.begin(); | ||
} | ||
SmallVectorImpl<ConstantRange>::const_iterator end() const { | ||
return Ranges.end(); | ||
} | ||
ConstantRange getRange(unsigned i) const { return Ranges[i]; } | ||
|
||
/// Return true if this list contains no members. | ||
bool empty() const { return Ranges.empty(); } | ||
|
||
/// Get the bit width of this ConstantRangeList. | ||
uint32_t getBitWidth() const { return 64; } | ||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// Return the number of ranges in this ConstantRangeList. | ||
size_t size() const { return Ranges.size(); } | ||
aeubanks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// Insert a new range to Ranges and keep the list ordered. | ||
void insert(const ConstantRange &NewRange); | ||
void insert(int64_t Lower, int64_t Upper) { | ||
insert(ConstantRange(APInt(64, Lower, /*isSigned=*/true), | ||
APInt(64, Upper, /*isSigned=*/true))); | ||
} | ||
|
||
/// Return true if this range list is equal to another range list. | ||
bool operator==(const ConstantRangeList &CRL) const { | ||
return Ranges == CRL.Ranges; | ||
} | ||
bool operator!=(const ConstantRangeList &CRL) const { | ||
return !operator==(CRL); | ||
} | ||
|
||
/// Print out the ranges to a stream. | ||
void print(raw_ostream &OS) const; | ||
|
||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||
void dump() const; | ||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#endif | ||
}; | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_IR_CONSTANTRANGELIST_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,7 @@ | |
#include "llvm/IR/CallingConv.h" | ||
#include "llvm/IR/Comdat.h" | ||
#include "llvm/IR/Constant.h" | ||
#include "llvm/IR/ConstantRangeList.h" | ||
#include "llvm/IR/Constants.h" | ||
#include "llvm/IR/DataLayout.h" | ||
#include "llvm/IR/DebugInfo.h" | ||
|
@@ -836,10 +837,10 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { | |
} | ||
|
||
Expected<ConstantRange> readConstantRange(ArrayRef<uint64_t> Record, | ||
unsigned &OpNum) { | ||
if (Record.size() - OpNum < 3) | ||
unsigned &OpNum, | ||
unsigned BitWidth) { | ||
if (Record.size() - OpNum < 2) | ||
return error("Too few records for range"); | ||
unsigned BitWidth = Record[OpNum++]; | ||
if (BitWidth > 64) { | ||
unsigned LowerActiveWords = Record[OpNum]; | ||
unsigned UpperActiveWords = Record[OpNum++] >> 32; | ||
|
@@ -859,6 +860,14 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { | |
} | ||
} | ||
|
||
Expected<ConstantRange> | ||
readBitWidthAndConstantRange(ArrayRef<uint64_t> Record, unsigned &OpNum) { | ||
if (Record.size() - OpNum < 1) | ||
return error("Too few records for range"); | ||
unsigned BitWidth = Record[OpNum++]; | ||
return readConstantRange(Record, OpNum, BitWidth); | ||
} | ||
|
||
/// Upgrades old-style typeless byval/sret/inalloca attributes by adding the | ||
/// corresponding argument's pointee type. Also upgrades intrinsics that now | ||
/// require an elementtype attribute. | ||
|
@@ -2172,6 +2181,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { | |
return Attribute::DeadOnUnwind; | ||
case bitc::ATTR_KIND_RANGE: | ||
return Attribute::Range; | ||
case bitc::ATTR_KIND_INITIALIZES: | ||
return Attribute::Initializes; | ||
} | ||
} | ||
|
||
|
@@ -2350,12 +2361,42 @@ Error BitcodeReader::parseAttributeGroupBlock() { | |
if (!Attribute::isConstantRangeAttrKind(Kind)) | ||
return error("Not a ConstantRange attribute"); | ||
|
||
Expected<ConstantRange> MaybeCR = readConstantRange(Record, i); | ||
Expected<ConstantRange> MaybeCR = | ||
readBitWidthAndConstantRange(Record, i); | ||
if (!MaybeCR) | ||
return MaybeCR.takeError(); | ||
i--; | ||
|
||
B.addConstantRangeAttr(Kind, MaybeCR.get()); | ||
} else if (Record[i] == 8) { | ||
Attribute::AttrKind Kind; | ||
|
||
i++; | ||
if (Error Err = parseAttrKind(Record[i++], &Kind)) | ||
return Err; | ||
if (!Attribute::isConstantRangeListAttrKind(Kind)) | ||
return error("Not a constant range list attribute"); | ||
|
||
SmallVector<ConstantRange, 2> Val; | ||
if (i + 2 > e) | ||
return error("Too few records for constant range list"); | ||
unsigned RangeSize = Record[i++]; | ||
unsigned BitWidth = Record[i++]; | ||
if (i + 2 * RangeSize > e) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can remove this hoisted There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, done! |
||
return error("Incomplete constant range list"); | ||
for (unsigned Idx = 0; Idx < RangeSize; ++Idx) { | ||
Expected<ConstantRange> MaybeCR = | ||
readConstantRange(Record, i, BitWidth); | ||
if (!MaybeCR) | ||
return MaybeCR.takeError(); | ||
Val.push_back(MaybeCR.get()); | ||
} | ||
i--; | ||
|
||
auto CRLOrNull = ConstantRangeList::getConstantRangeList(Val); | ||
if (!CRLOrNull.has_value()) | ||
return error("Invalid (unordered or overlapping) range list"); | ||
B.addConstantRangeListAttr(Kind, *CRLOrNull); | ||
} else { | ||
return error("Invalid attribute group entry"); | ||
} | ||
|
@@ -3370,7 +3411,8 @@ Error BitcodeReader::parseConstants() { | |
(void)InRangeIndex; | ||
} else if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE) { | ||
Flags = Record[OpNum++]; | ||
Expected<ConstantRange> MaybeInRange = readConstantRange(Record, OpNum); | ||
Expected<ConstantRange> MaybeInRange = | ||
readBitWidthAndConstantRange(Record, OpNum); | ||
if (!MaybeInRange) | ||
return MaybeInRange.takeError(); | ||
InRange = MaybeInRange.get(); | ||
|
Uh oh!
There was an error while loading. Please reload this page.