-
Notifications
You must be signed in to change notification settings - Fork 13.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 1 commit
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 |
---|---|---|
|
@@ -275,6 +275,7 @@ namespace llvm { | |
Loc = Lex.getLoc(); | ||
return parseUInt64(Val); | ||
} | ||
bool parseInt64(int64_t &Val); | ||
bool parseFlag(unsigned &Val); | ||
|
||
bool parseStringAttribute(AttrBuilder &B); | ||
|
@@ -307,6 +308,10 @@ namespace llvm { | |
bool AllowParens = false); | ||
bool parseOptionalCodeModel(CodeModel::Model &model); | ||
bool parseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes); | ||
bool parseConstRange(std::pair<int64_t, int64_t> &Range); | ||
bool parseInitializedRanges( | ||
lltok::Kind AttrKind, | ||
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. can the AttrKind be hardcoded within the function instead of taking as parameter? (unlike DerefAttrBytes, there is only one variation of the attribute, I believe?) |
||
SmallVector<std::pair<int64_t, int64_t>, 16> &Ranges); | ||
bool parseOptionalUWTableKind(UWTableKind &Kind); | ||
bool parseAllocKind(AllocFnKind &Kind); | ||
std::optional<MemoryEffects> parseMemoryAttr(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,8 @@ class Attribute { | |
|
||
static const unsigned NumIntAttrKinds = LastIntAttr - FirstIntAttr + 1; | ||
static const unsigned NumTypeAttrKinds = LastTypeAttr - FirstTypeAttr + 1; | ||
static const unsigned NumConstRangeListAttrKinds = | ||
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. Is this used by anything (if not, can remove)? I don't see the ConstantRangeAttrKind version of it, and hard to see "NumTypeAttrKinds" used |
||
LastConstRangeListAttr - FirstConstRangeListAttr + 1; | ||
|
||
static bool isEnumAttrKind(AttrKind Kind) { | ||
return Kind >= FirstEnumAttr && Kind <= LastEnumAttr; | ||
|
@@ -107,6 +109,9 @@ class Attribute { | |
static bool isConstantRangeAttrKind(AttrKind Kind) { | ||
return Kind >= FirstConstantRangeAttr && Kind <= LastConstantRangeAttr; | ||
} | ||
static bool isConstRangeListAttrKind(AttrKind Kind) { | ||
return Kind >= FirstConstRangeListAttr && Kind <= LastConstRangeListAttr; | ||
} | ||
|
||
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, | ||
SmallVector<std::pair<int64_t, int64_t>, 16> &Ranges); | ||
|
||
/// Return a uniquified Attribute object that has the specific | ||
/// alignment set. | ||
|
@@ -186,6 +193,9 @@ class Attribute { | |
/// Return true if the attribute is a type attribute. | ||
bool isTypeAttribute() const; | ||
|
||
/// Return true if the attribute is a const range list attribute. | ||
bool isConstRangeListAttribute() 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: wonder if should s/Const/Constant/ to be consistent with isConstantRangeAttribute, etc. 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. +1, no need to abbreviate |
||
|
||
/// Return true if the attribute is a ConstantRange attribute. | ||
bool isConstantRangeAttribute() const; | ||
|
||
|
@@ -226,6 +236,10 @@ class Attribute { | |
/// attribute to be a ConstantRange attribute. | ||
ConstantRange getValueAsConstantRange() const; | ||
|
||
/// Return the attribute's value as a const range list. This requires the | ||
/// attribute to be a const range list attribute. | ||
SmallVector<std::pair<int64_t, int64_t>, 16> getValueAsRanges() 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. we should use 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. also, 16 elements for the small vector optimization seems very high, I feel the vast majority of cases will be at most 4. I'd choose 4 (or even 2) 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. Is it possible to return an ArrayRef instead of a copy? Will the underlying storage lifetime work out? |
||
|
||
/// Returns the alignment field of an attribute as a byte alignment | ||
/// value. | ||
MaybeAlign getAlignment() const; | ||
|
@@ -1169,6 +1183,11 @@ class AttrBuilder { | |
/// Add a type attribute with the given type. | ||
AttrBuilder &addTypeAttr(Attribute::AttrKind Kind, Type *Ty); | ||
|
||
/// Add a const range list attribute with the given ranges. | ||
AttrBuilder & | ||
addConstRangeListAttr(Attribute::AttrKind Kind, | ||
SmallVector<std::pair<int64_t, int64_t>, 16> &Ranges); | ||
|
||
/// This turns a byval type into the form used internally in Attribute. | ||
AttrBuilder &addByValAttr(Type *Ty); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,9 @@ class IntAttr<string S, list<AttrProperty> P> : Attr<S, P>; | |
/// Type attribute. | ||
class TypeAttr<string S, list<AttrProperty> P> : Attr<S, P>; | ||
|
||
/// Const range list attribute. | ||
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: put closer to the ConstantRangeAttr? |
||
class ConstRangeListAttr<string S, list<AttrProperty> P>: Attr<S, P>; | ||
|
||
/// StringBool attribute. | ||
class StrBoolAttr<string S> : Attr<S, []>; | ||
|
||
|
@@ -318,6 +321,9 @@ def Writable : EnumAttr<"writable", [ParamAttr]>; | |
/// Function only writes to memory. | ||
def WriteOnly : EnumAttr<"writeonly", [ParamAttr]>; | ||
|
||
/// Pointer argument memory [%p+LoN, %p+HiN) is initialized. | ||
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. The list looks almost sorted, so may be better to put it near InAlloca or ? |
||
def Initialized : ConstRangeListAttr<"initialized", [ParamAttr]>; | ||
|
||
/// Zero extended before/after call. | ||
def ZExt : EnumAttr<"zeroext", [ParamAttr, RetAttr]>; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1566,6 +1566,13 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, | |
B.addDereferenceableOrNullAttr(Bytes); | ||
return false; | ||
} | ||
case Attribute::Initialized: { | ||
SmallVector<std::pair<int64_t, int64_t>, 16> Ranges; | ||
if (parseInitializedRanges(lltok::kw_initialized, Ranges)) | ||
return true; | ||
B.addConstRangeListAttr(Attribute::Initialized, Ranges); | ||
return false; | ||
} | ||
case Attribute::UWTable: { | ||
UWTableKind Kind; | ||
if (parseOptionalUWTableKind(Kind)) | ||
|
@@ -1850,6 +1857,16 @@ bool LLParser::parseUInt64(uint64_t &Val) { | |
return false; | ||
} | ||
|
||
/// parseInt64 | ||
/// ::= int64_t | ||
bool LLParser::parseInt64(int64_t &Val) { | ||
if (Lex.getKind() != lltok::APSInt) | ||
return tokError("expected signed integer"); | ||
Val = Lex.getAPSIntVal().extend(64).getSExtValue(); | ||
Lex.Lex(); | ||
return false; | ||
} | ||
|
||
/// parseTLSModel | ||
/// := 'localdynamic' | ||
/// := 'initialexec' | ||
|
@@ -2364,6 +2381,54 @@ bool LLParser::parseOptionalDerefAttrBytes(lltok::Kind AttrKind, | |
return false; | ||
} | ||
|
||
bool LLParser::parseConstRange(std::pair<int64_t, int64_t> &Range) { | ||
LocTy LparenLoc = Lex.getLoc(); | ||
if (!EatIfPresent(lltok::lparen)) | ||
return error(LparenLoc, "expected'('"); | ||
|
||
if (parseInt64(Range.first)) | ||
return true; | ||
|
||
if (EatIfPresent(lltok::comma)) { | ||
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. should it be an error to be missing the comma? |
||
if (parseInt64(Range.second)) { | ||
return true; | ||
} | ||
} | ||
|
||
LocTy RparenLoc = Lex.getLoc(); | ||
if (!EatIfPresent(lltok::rparen)) | ||
return error(RparenLoc, "expected ')'"); | ||
|
||
return false; | ||
} | ||
|
||
bool LLParser::parseInitializedRanges( | ||
lltok::Kind AttrKind, | ||
SmallVector<std::pair<int64_t, int64_t>, 16> &Ranges) { | ||
assert(AttrKind == lltok::kw_initialized); | ||
Ranges.clear(); | ||
|
||
if (!EatIfPresent(AttrKind)) | ||
return false; | ||
|
||
LocTy LparenLoc = Lex.getLoc(); | ||
if (!EatIfPresent(lltok::lparen)) | ||
return error(LparenLoc, "expected '('"); | ||
|
||
// Parse each range. | ||
do { | ||
std::pair<int64_t, int64_t> Range; | ||
if (parseConstRange(Range)) | ||
return true; | ||
Ranges.push_back(Range); | ||
} while (EatIfPresent(lltok::comma)); | ||
|
||
LocTy RparenLoc = Lex.getLoc(); | ||
if (!EatIfPresent(lltok::rparen)) | ||
return error(RparenLoc, "expected ')'"); | ||
return false; | ||
} | ||
|
||
bool LLParser::parseOptionalUWTableKind(UWTableKind &Kind) { | ||
Lex.Lex(); | ||
Kind = UWTableKind::Default; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2129,6 +2129,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { | |||||
return Attribute::DeadOnUnwind; | ||||||
case bitc::ATTR_KIND_RANGE: | ||||||
return Attribute::Range; | ||||||
case bitc::ATTR_KIND_INITIALIZED: | ||||||
return Attribute::Initialized; | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -2313,6 +2315,22 @@ Error BitcodeReader::parseAttributeGroupBlock() { | |||||
i--; | ||||||
|
||||||
B.addConstantRangeAttr(Kind, MaybeCR.get()); | ||||||
} else if (Record[i] == 8 || Record[i] == 9) { | ||||||
Attribute::AttrKind Kind; | ||||||
if (Error Err = parseAttrKind(Record[++i], &Kind)) | ||||||
return Err; | ||||||
if (!Attribute::isConstRangeListAttrKind(Kind)) | ||||||
return error("Not a const range list attribute"); | ||||||
|
||||||
SmallVector<std::pair<int64_t, int64_t>, 16> Ranges; | ||||||
int RangeSize = Record[++i]; | ||||||
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. Maybe assert i + (RangeSize * 2) < 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. Done! 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. each loop iter up to 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. Oops, good catch! Done. 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.
Suggested change
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! |
||||||
for (int Idx = 0; Idx < RangeSize; ++Idx) { | ||||||
int Start = Record[++i]; | ||||||
int End = Record[++i]; | ||||||
Ranges.push_back(std::make_pair(Start, End)); | ||||||
} | ||||||
|
||||||
B.addConstRangeListAttr(Kind, Ranges); | ||||||
} else { | ||||||
return error("Invalid attribute group entry"); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -846,6 +846,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { | |
return bitc::ATTR_KIND_DEAD_ON_UNWIND; | ||
case Attribute::Range: | ||
return bitc::ATTR_KIND_RANGE; | ||
case Attribute::Initialized: | ||
return bitc::ATTR_KIND_INITIALIZED; | ||
case Attribute::EndAttrKinds: | ||
llvm_unreachable("Can not encode end-attribute kinds marker."); | ||
case Attribute::None: | ||
|
@@ -930,11 +932,24 @@ void ModuleBitcodeWriter::writeAttributeGroupTable() { | |
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); | ||
if (Ty) | ||
Record.push_back(VE.getTypeID(Attr.getValueAsType())); | ||
} else { | ||
} else if (Attr.isConstantRangeAttribute()) { | ||
assert(Attr.isConstantRangeAttribute()); | ||
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: can remove the assert? |
||
Record.push_back(7); | ||
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); | ||
emitConstantRange(Record, Attr.getValueAsConstantRange()); | ||
} else { | ||
assert(Attr.isConstRangeListAttribute()); | ||
const auto &Ranges = Attr.getValueAsRanges(); | ||
|
||
Record.push_back(Ranges.empty() ? 8 : 9); | ||
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); | ||
Record.push_back(Ranges.size()); | ||
if (!Ranges.empty()) { | ||
for (const auto &Range : Ranges) { | ||
Record.push_back(Range.first); | ||
Record.push_back(Range.second); | ||
} | ||
} | ||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ class AttributeImpl : public FoldingSetNode { | |
StringAttrEntry, | ||
TypeAttrEntry, | ||
ConstantRangeAttrEntry, | ||
ConstRangeListAttrEntry, | ||
}; | ||
|
||
AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} | ||
|
@@ -64,6 +65,9 @@ class AttributeImpl : public FoldingSetNode { | |
bool isConstantRangeAttribute() const { | ||
return KindID == ConstantRangeAttrEntry; | ||
} | ||
bool isConstRangeListAttribute() const { | ||
return KindID == ConstRangeListAttrEntry; | ||
} | ||
|
||
bool hasAttribute(Attribute::AttrKind A) const; | ||
bool hasAttribute(StringRef Kind) const; | ||
|
@@ -79,6 +83,8 @@ class AttributeImpl : public FoldingSetNode { | |
|
||
ConstantRange getValueAsConstantRange() const; | ||
|
||
SmallVector<std::pair<int64_t, int64_t>, 16> getValueAsRanges() const; | ||
|
||
/// Used when sorting the attributes. | ||
bool operator<(const AttributeImpl &AI) const; | ||
|
||
|
@@ -91,8 +97,10 @@ class AttributeImpl : public FoldingSetNode { | |
Profile(ID, getKindAsString(), getValueAsString()); | ||
else if (isTypeAttribute()) | ||
Profile(ID, getKindAsEnum(), getValueAsType()); | ||
else | ||
else if (isConstantRangeAttribute()) | ||
Profile(ID, getKindAsEnum(), getValueAsConstantRange()); | ||
else | ||
Profile(ID, getKindAsEnum(), getValueAsRanges()); | ||
} | ||
|
||
static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind) { | ||
|
@@ -124,6 +132,13 @@ class AttributeImpl : public FoldingSetNode { | |
ID.AddInteger(CR.getLower()); | ||
ID.AddInteger(CR.getUpper()); | ||
} | ||
|
||
static void | ||
Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, | ||
const SmallVector<std::pair<int64_t, int64_t>, 16> &Ranges) { | ||
ID.AddInteger(Kind); | ||
ID.AddRanges(Ranges); | ||
} | ||
}; | ||
|
||
static_assert(std::is_trivially_destructible<AttributeImpl>::value, | ||
|
@@ -222,6 +237,20 @@ class ConstantRangeAttributeImpl : public EnumAttributeImpl { | |
ConstantRange getConstantRangeValue() const { return CR; } | ||
}; | ||
|
||
class ConstRangeListAttributeImpl : public EnumAttributeImpl { | ||
SmallVector<std::pair<int64_t, int64_t>, 16> Ranges; | ||
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. Perhaps something smaller than 16? What is the typical number of ranges? |
||
|
||
public: | ||
ConstRangeListAttributeImpl( | ||
Attribute::AttrKind Kind, | ||
SmallVector<std::pair<int64_t, int64_t>, 16> &Ranges) | ||
: EnumAttributeImpl(ConstRangeListAttrEntry, Kind), Ranges(Ranges) {} | ||
|
||
SmallVector<std::pair<int64_t, int64_t>, 16> getRangesValue() const { | ||
return Ranges; | ||
} | ||
}; | ||
|
||
class AttributeBitSet { | ||
/// Bitset with a bit for each available attribute Attribute::AttrKind. | ||
uint8_t AvailableAttrs[12] = {}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to use ArrayRef or something to not need specific SmallVector inline size of 16 here? "Prefer to use ArrayRef or SmallVectorImpl as a parameter type." under https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h