Skip to content

Commit 7377ed4

Browse files
Thomas Symallatsymalla-AMD
authored andcommitted
Add support for immutable attributes.
Sometimes we don't want or can't update operands with a auto-generated setter method, so this change adds support to make attributes immutable.
1 parent 28eac73 commit 7377ed4

File tree

7 files changed

+154
-19
lines changed

7 files changed

+154
-19
lines changed

example/ExampleDialect.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ def VectorKindLittleEndian : CppConstant<"xd::VectorKind::LittleEndian">;
3636
def VectorKindBigEndian : CppConstant<"xd::VectorKind::BigEndian">;
3737
def VectorKindMiddleEndian : CppConstant<"xd::VectorKind::MiddleEndian">;
3838

39+
def ImmutableAttrI1 : IntegerAttr<"bool"> {
40+
let isImmutable = true;
41+
}
42+
43+
def : AttrLlvmType<ImmutableAttrI1, I1>;
44+
3945
def isReasonableVectorKind : TgPredicate<
4046
(args AttrVectorKind:$kind),
4147
(eq $kind, (or VectorKindLittleEndian, VectorKindBigEndian))>;
@@ -301,3 +307,13 @@ def InstNameConflictVarargsOp : Op<ExampleDialect, "inst.name.conflict.varargs",
301307
Like InstNameConflictOp but with varargs
302308
}];
303309
}
310+
311+
def ImmutableOp : Op<ExampleDialect, "immutable.op", [WillReturn]> {
312+
let results = (outs);
313+
let arguments = (ins ImmutableAttrI1:$val);
314+
315+
let summary = "demonstrate how an argument will not get a setter method";
316+
let description = [{
317+
Make an argument immutable
318+
}];
319+
}

include/llvm-dialects/Dialect/Dialect.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class Attr<string cppType_> : MetaType {
6969
// A check statement that is issued before using the C++ value in builders.
7070
// $0 is the C++ value.
7171
string check = "";
72+
73+
// Overriding prevents generating a setter method. Attributes are mutable by default.
74+
bit isImmutable = false;
7275
}
7376

7477
class IntegerAttr<string cppType_> : Attr<cppType_> {

include/llvm-dialects/TableGen/Constraints.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class MetaType {
203203
bool isTypeArg() const { return m_kind == Kind::Type; }
204204
bool isValueArg() const { return m_kind == Kind::Value; }
205205
bool isVarArgList() const { return m_kind == Kind::VarArgList; }
206+
bool isImmutable() const;
206207

207208
protected:
208209
MetaType(Kind kind) : m_kind(kind) {}
@@ -231,6 +232,7 @@ class Attr : public MetaType {
231232
llvm::StringRef getToUnsigned() const { return m_toUnsigned; }
232233
llvm::StringRef getFromUnsigned() const { return m_fromUnsigned; }
233234
llvm::StringRef getCheck() const { return m_check; }
235+
bool getIsImmutable() const { return m_isImmutable; }
234236

235237
// Set the LLVMType once -- used during initialization to break a circular
236238
// dependency in how IntegerType is defined.
@@ -249,6 +251,7 @@ class Attr : public MetaType {
249251
std::string m_toUnsigned;
250252
std::string m_fromUnsigned;
251253
std::string m_check;
254+
bool m_isImmutable;
252255
};
253256

254257
} // namespace llvm_dialects

lib/TableGen/Constraints.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,13 @@ StringRef MetaType::getBuilderCppType() const {
361361
return getCppType();
362362
}
363363

364+
bool MetaType::isImmutable() const {
365+
if (auto *attr = dyn_cast<Attr>(this))
366+
return attr->getIsImmutable();
367+
368+
return false;
369+
}
370+
364371
/// Return the C++ expression @p value transformed to be suitable for printing
365372
/// using LLVM's raw_ostream.
366373
std::string MetaType::printable(const MetaType *type, llvm::StringRef value) {
@@ -394,6 +401,7 @@ std::unique_ptr<Attr> Attr::parse(raw_ostream &errs,
394401
attr->m_toUnsigned = record->getValueAsString("toUnsigned");
395402
attr->m_fromUnsigned = record->getValueAsString("fromUnsigned");
396403
attr->m_check = record->getValueAsString("check");
404+
attr->m_isImmutable = record->getValueAsBit("isImmutable");
397405

398406
return attr;
399407
}

lib/TableGen/Operations.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ void OperationBase::emitArgumentAccessorDeclarations(llvm::raw_ostream &out,
160160
FmtContext &fmt) const {
161161
for (const auto &arg : m_arguments) {
162162
std::string defaultDeclaration = "$0 get$1();";
163-
if (!arg.type->isVarArgList()) {
163+
if (!arg.type->isVarArgList() && !arg.type->isImmutable()) {
164164
defaultDeclaration += R"(
165165
void set$1($0 $2);
166166
)";
@@ -205,6 +205,9 @@ void AccessorBuilder::emitGetterDefinition() const {
205205
}
206206

207207
void AccessorBuilder::emitSetterDefinition() const {
208+
if (m_arg.type->isImmutable())
209+
return;
210+
208211
std::string toLlvm = m_arg.name;
209212

210213
if (auto *attr = dyn_cast<Attr>(m_arg.type)) {

test/example/generated/ExampleDialect.cpp.inc

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ namespace xd {
6969
state.setError();
7070
});
7171

72+
builder.add<ImmutableOp>([](::llvm_dialects::VerifierState &state, ImmutableOp &op) {
73+
if (!op.verifier(state.out()))
74+
state.setError();
75+
});
76+
7277
builder.add<InsertElementOp>([](::llvm_dialects::VerifierState &state, InsertElementOp &op) {
7378
if (!op.verifier(state.out()))
7479
state.setError();
@@ -149,21 +154,21 @@ namespace xd {
149154
::llvm::AttrBuilder attrBuilder{context};
150155
attrBuilder.addAttribute(::llvm::Attribute::NoUnwind);
151156
attrBuilder.addAttribute(::llvm::Attribute::WillReturn);
152-
attrBuilder.addMemoryAttr(::llvm::MemoryEffects(::llvm::MemoryEffects::Location::InaccessibleMem, ::llvm::ModRefInfo::Mod));
157+
attrBuilder.addMemoryAttr(::llvm::MemoryEffects(::llvm::ModRefInfo::Ref));
153158
m_attributeLists[0] = ::llvm::AttributeList::get(context, ::llvm::AttributeList::FunctionIndex, attrBuilder);
154159
}
155160
{
156161
::llvm::AttrBuilder attrBuilder{context};
157162
attrBuilder.addAttribute(::llvm::Attribute::NoUnwind);
158163
attrBuilder.addAttribute(::llvm::Attribute::WillReturn);
159-
attrBuilder.addMemoryAttr(::llvm::MemoryEffects::none());
164+
attrBuilder.addMemoryAttr(::llvm::MemoryEffects(::llvm::MemoryEffects::Location::InaccessibleMem, ::llvm::ModRefInfo::Mod));
160165
m_attributeLists[1] = ::llvm::AttributeList::get(context, ::llvm::AttributeList::FunctionIndex, attrBuilder);
161166
}
162167
{
163168
::llvm::AttrBuilder attrBuilder{context};
164169
attrBuilder.addAttribute(::llvm::Attribute::NoUnwind);
165170
attrBuilder.addAttribute(::llvm::Attribute::WillReturn);
166-
attrBuilder.addMemoryAttr(::llvm::MemoryEffects(::llvm::ModRefInfo::Ref));
171+
attrBuilder.addMemoryAttr(::llvm::MemoryEffects::none());
167172
m_attributeLists[2] = ::llvm::AttributeList::get(context, ::llvm::AttributeList::FunctionIndex, attrBuilder);
168173
}
169174
{
@@ -324,7 +329,7 @@ return true;
324329

325330

326331
const ::llvm::AttributeList attrs
327-
= ExampleDialect::get(context).getAttributeList(1);
332+
= ExampleDialect::get(context).getAttributeList(2);
328333
auto fnType = ::llvm::FunctionType::get(::llvm::IntegerType::get(context, 32), {
329334
lhs->getType(),
330335
rhs->getType(),
@@ -446,7 +451,7 @@ uint32_t const extra = getExtra();
446451

447452

448453
const ::llvm::AttributeList attrs
449-
= ExampleDialect::get(context).getAttributeList(1);
454+
= ExampleDialect::get(context).getAttributeList(2);
450455

451456
std::string mangledName =
452457
::llvm_dialects::getMangledName(s_name, {lhs->getType()});
@@ -541,7 +546,7 @@ rhs
541546

542547

543548
const ::llvm::AttributeList attrs
544-
= ExampleDialect::get(context).getAttributeList(1);
549+
= ExampleDialect::get(context).getAttributeList(2);
545550

546551
std::string mangledName =
547552
::llvm_dialects::getMangledName(s_name, {::llvm::cast<XdVectorType>(vector->getType())->getElementType()});
@@ -645,7 +650,7 @@ index
645650

646651

647652
const ::llvm::AttributeList attrs
648-
= ExampleDialect::get(context).getAttributeList(1);
653+
= ExampleDialect::get(context).getAttributeList(2);
649654

650655
std::string mangledName =
651656
::llvm_dialects::getMangledName(s_name, {resultType});
@@ -815,7 +820,7 @@ source
815820

816821

817822
const ::llvm::AttributeList attrs
818-
= ExampleDialect::get(context).getAttributeList(1);
823+
= ExampleDialect::get(context).getAttributeList(2);
819824
auto fnType = ::llvm::FunctionType::get(XdHandleType::get(context), {
820825
}, false);
821826

@@ -877,7 +882,7 @@ source
877882

878883

879884
const ::llvm::AttributeList attrs
880-
= ExampleDialect::get(context).getAttributeList(1);
885+
= ExampleDialect::get(context).getAttributeList(2);
881886

882887
std::string mangledName =
883888
::llvm_dialects::getMangledName(s_name, {resultType});
@@ -975,7 +980,7 @@ source
975980

976981

977982
const ::llvm::AttributeList attrs
978-
= ExampleDialect::get(context).getAttributeList(1);
983+
= ExampleDialect::get(context).getAttributeList(2);
979984

980985
std::string mangledName =
981986
::llvm_dialects::getMangledName(s_name, {resultType});
@@ -1064,6 +1069,75 @@ source
10641069

10651070

10661071

1072+
const ::llvm::StringLiteral ImmutableOp::s_name{"xd.immutable.op"};
1073+
1074+
ImmutableOp* ImmutableOp::create(llvm_dialects::Builder& b, bool val, const llvm::Twine &instName) {
1075+
::llvm::LLVMContext& context = b.getContext();
1076+
(void)context;
1077+
::llvm::Module& module = *b.GetInsertBlock()->getModule();
1078+
1079+
1080+
const ::llvm::AttributeList attrs
1081+
= ExampleDialect::get(context).getAttributeList(4);
1082+
auto fnType = ::llvm::FunctionType::get(::llvm::Type::getVoidTy(context), {
1083+
::llvm::IntegerType::get(context, 1),
1084+
}, false);
1085+
1086+
auto fn = module.getOrInsertFunction(s_name, fnType, attrs);
1087+
::llvm::SmallString<32> newName;
1088+
for (unsigned i = 0; !::llvm::isa<::llvm::Function>(fn.getCallee()) ||
1089+
::llvm::cast<::llvm::Function>(fn.getCallee())->getFunctionType() != fn.getFunctionType(); i++) {
1090+
// If a function with the same name but a different types already exists,
1091+
// we get a bitcast of a function or a function with the wrong type.
1092+
// Try new names until we get one with the correct type.
1093+
newName = "";
1094+
::llvm::raw_svector_ostream newNameStream(newName);
1095+
newNameStream << s_name << "_" << i;
1096+
fn = module.getOrInsertFunction(newNameStream.str(), fnType, attrs);
1097+
}
1098+
assert(::llvm::isa<::llvm::Function>(fn.getCallee()));
1099+
assert(fn.getFunctionType() == fnType);
1100+
assert(::llvm::cast<::llvm::Function>(fn.getCallee())->getFunctionType() == fn.getFunctionType());
1101+
1102+
1103+
::llvm::SmallVector<::llvm::Value*, 1> args = {
1104+
::llvm::ConstantInt::get(::llvm::IntegerType::get(context, 1), val)
1105+
};
1106+
1107+
return ::llvm::cast<ImmutableOp>(b.CreateCall(fn, args, instName));
1108+
}
1109+
1110+
1111+
bool ImmutableOp::verifier(::llvm::raw_ostream &errs) {
1112+
::llvm::LLVMContext &context = getModule()->getContext();
1113+
(void)context;
1114+
1115+
using ::llvm_dialects::printable;
1116+
1117+
if (arg_size() != 1) {
1118+
errs << " wrong number of arguments: " << arg_size()
1119+
<< ", expected 1\n";
1120+
return false;
1121+
}
1122+
1123+
if (getArgOperand(0)->getType() != ::llvm::IntegerType::get(context, 1)) {
1124+
errs << " argument 0 (val) has type: "
1125+
<< *getArgOperand(0)->getType() << '\n';
1126+
errs << " expected: " << *::llvm::IntegerType::get(context, 1) << '\n';
1127+
return false;
1128+
}
1129+
bool const val = getVal();
1130+
(void)val;
1131+
return true;
1132+
}
1133+
1134+
1135+
bool ImmutableOp::getVal() {
1136+
return ::llvm::cast<::llvm::ConstantInt>(getArgOperand(0))->getZExtValue() ;
1137+
}
1138+
1139+
1140+
10671141
const ::llvm::StringLiteral InsertElementOp::s_name{"xd.insertelement"};
10681142

10691143
InsertElementOp* InsertElementOp::create(llvm_dialects::Builder& b, ::llvm::Value * vector, ::llvm::Value * value, ::llvm::Value * index, const llvm::Twine &instName) {
@@ -1073,7 +1147,7 @@ source
10731147

10741148

10751149
const ::llvm::AttributeList attrs
1076-
= ExampleDialect::get(context).getAttributeList(1);
1150+
= ExampleDialect::get(context).getAttributeList(2);
10771151

10781152
std::string mangledName =
10791153
::llvm_dialects::getMangledName(s_name, {vector->getType()});
@@ -1539,7 +1613,7 @@ instName
15391613

15401614

15411615
const ::llvm::AttributeList attrs
1542-
= ExampleDialect::get(context).getAttributeList(0);
1616+
= ExampleDialect::get(context).getAttributeList(1);
15431617
auto fnType = ::llvm::FunctionType::get(::llvm::Type::getVoidTy(context), true);
15441618

15451619
auto fn = module.getOrInsertFunction(s_name, fnType, attrs);
@@ -1602,7 +1676,7 @@ data
16021676

16031677

16041678
const ::llvm::AttributeList attrs
1605-
= ExampleDialect::get(context).getAttributeList(1);
1679+
= ExampleDialect::get(context).getAttributeList(2);
16061680
auto fnType = ::llvm::FunctionType::get(::llvm::IntegerType::get(context, 64), true);
16071681

16081682
auto fn = module.getOrInsertFunction(s_name, fnType, attrs);
@@ -1676,7 +1750,7 @@ data
16761750

16771751

16781752
const ::llvm::AttributeList attrs
1679-
= ExampleDialect::get(context).getAttributeList(2);
1753+
= ExampleDialect::get(context).getAttributeList(0);
16801754

16811755
std::string mangledName =
16821756
::llvm_dialects::getMangledName(s_name, {initial->getType()});
@@ -1768,7 +1842,7 @@ initial
17681842

17691843

17701844
const ::llvm::AttributeList attrs
1771-
= ExampleDialect::get(context).getAttributeList(2);
1845+
= ExampleDialect::get(context).getAttributeList(0);
17721846

17731847
std::string mangledName =
17741848
::llvm_dialects::getMangledName(s_name, {initial->getType()});
@@ -1860,7 +1934,7 @@ initial
18601934

18611935

18621936
const ::llvm::AttributeList attrs
1863-
= ExampleDialect::get(context).getAttributeList(2);
1937+
= ExampleDialect::get(context).getAttributeList(0);
18641938

18651939
std::string mangledName =
18661940
::llvm_dialects::getMangledName(s_name, {initial->getType()});
@@ -1952,7 +2026,7 @@ initial
19522026

19532027

19542028
const ::llvm::AttributeList attrs
1955-
= ExampleDialect::get(context).getAttributeList(0);
2029+
= ExampleDialect::get(context).getAttributeList(1);
19562030
auto fnType = ::llvm::FunctionType::get(::llvm::Type::getVoidTy(context), true);
19572031

19582032
auto fn = module.getOrInsertFunction(s_name, fnType, attrs);
@@ -2015,7 +2089,7 @@ data
20152089

20162090

20172091
const ::llvm::AttributeList attrs
2018-
= ExampleDialect::get(context).getAttributeList(0);
2092+
= ExampleDialect::get(context).getAttributeList(1);
20192093
auto fnType = ::llvm::FunctionType::get(::llvm::Type::getVoidTy(context), true);
20202094

20212095
auto fn = module.getOrInsertFunction(s_name, fnType, attrs);
@@ -2133,6 +2207,14 @@ data
21332207
}
21342208

21352209

2210+
template <>
2211+
const ::llvm_dialects::OpDescription &
2212+
::llvm_dialects::OpDescription::get<xd::ImmutableOp>() {
2213+
static const ::llvm_dialects::OpDescription desc{false, "xd.immutable.op"};
2214+
return desc;
2215+
}
2216+
2217+
21362218
template <>
21372219
const ::llvm_dialects::OpDescription &
21382220
::llvm_dialects::OpDescription::get<xd::InsertElementOp>() {

test/example/generated/ExampleDialect.h.inc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,26 @@ bool verifier(::llvm::raw_ostream &errs);
269269
::llvm::Value * getResult();
270270

271271

272+
};
273+
274+
class ImmutableOp : public ::llvm::CallInst {
275+
static const ::llvm::StringLiteral s_name; //{"xd.immutable.op"};
276+
277+
public:
278+
static bool classof(const ::llvm::CallInst* i) {
279+
return ::llvm_dialects::detail::isSimpleOperation(i, s_name);
280+
}
281+
static bool classof(const ::llvm::Value* v) {
282+
return ::llvm::isa<::llvm::CallInst>(v) &&
283+
classof(::llvm::cast<::llvm::CallInst>(v));
284+
}
285+
static ImmutableOp* create(::llvm_dialects::Builder& b, bool val, const llvm::Twine &instName = "");
286+
287+
bool verifier(::llvm::raw_ostream &errs);
288+
289+
bool getVal();
290+
291+
272292
};
273293

274294
class InsertElementOp : public ::llvm::CallInst {

0 commit comments

Comments
 (0)