Skip to content
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

Support traits on return value and parameters #110

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 36 additions & 20 deletions include/llvm-dialects/Dialect/Dialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -320,29 +320,43 @@ multiclass AttrEnum<string cppType_> {
/// Traits generally map to llvm::Attributes.
// ============================================================================

class Trait;
class TraitProperty;
def FnTrait : TraitProperty;
def ParamTrait : TraitProperty;
def RetTrait : TraitProperty;

class LlvmEnumAttributeTrait<string llvmEnum_> : Trait {
class Trait<list<TraitProperty> P>{
list<TraitProperty> Properties = P;
}

class LlvmEnumAttributeTrait<string llvmEnum_, list<TraitProperty> P> : Trait<P> {
string llvmEnum = llvmEnum_;
}

def NoUnwind : LlvmEnumAttributeTrait<"NoUnwind">;
def WillReturn : LlvmEnumAttributeTrait<"WillReturn">;
def NoReturn : LlvmEnumAttributeTrait<"NoReturn">;
def NoRecurse : LlvmEnumAttributeTrait<"NoRecurse">;
def NoSync : LlvmEnumAttributeTrait<"NoSync">;
def NoFree : LlvmEnumAttributeTrait<"NoFree">;
def MustProgress : LlvmEnumAttributeTrait<"MustProgress">;
def NoCallback : LlvmEnumAttributeTrait<"NoCallback">;
def NoDuplicate : LlvmEnumAttributeTrait<"NoDuplicate">;
def NoBuiltin : LlvmEnumAttributeTrait<"NoBuiltin">;
def Builtin : LlvmEnumAttributeTrait<"Builtin">;
def InlineHint : LlvmEnumAttributeTrait<"InlineHint">;
def AlwaysInline : LlvmEnumAttributeTrait<"AlwaysInline">;
def Cold : LlvmEnumAttributeTrait<"Cold">;
def Hot : LlvmEnumAttributeTrait<"Hot">;
def Convergent : LlvmEnumAttributeTrait<"Convergent">;
def Speculatable : LlvmEnumAttributeTrait<"Speculatable">;
def NoUnwind : LlvmEnumAttributeTrait<"NoUnwind", [FnTrait]>;
def WillReturn : LlvmEnumAttributeTrait<"WillReturn", [FnTrait]>;
def NoReturn : LlvmEnumAttributeTrait<"NoReturn", [FnTrait]>;
def NoRecurse : LlvmEnumAttributeTrait<"NoRecurse", [FnTrait]>;
def NoSync : LlvmEnumAttributeTrait<"NoSync", [FnTrait]>;
def NoFree : LlvmEnumAttributeTrait<"NoFree", [FnTrait]>;
def MustProgress : LlvmEnumAttributeTrait<"MustProgress", [FnTrait]>;
def NoCallback : LlvmEnumAttributeTrait<"NoCallback", [FnTrait]>;
def NoDuplicate : LlvmEnumAttributeTrait<"NoDuplicate", [FnTrait]>;
def NoBuiltin : LlvmEnumAttributeTrait<"NoBuiltin", [FnTrait]>;
def Builtin : LlvmEnumAttributeTrait<"Builtin", [FnTrait]>;
def InlineHint : LlvmEnumAttributeTrait<"InlineHint", [FnTrait]>;
def AlwaysInline : LlvmEnumAttributeTrait<"AlwaysInline", [FnTrait]>;
def Cold : LlvmEnumAttributeTrait<"Cold", [FnTrait]>;
def Hot : LlvmEnumAttributeTrait<"Hot", [FnTrait]>;
def Convergent : LlvmEnumAttributeTrait<"Convergent", [FnTrait]>;
def Speculatable : LlvmEnumAttributeTrait<"Speculatable", [FnTrait]>;

def NoCapture : LlvmEnumAttributeTrait<"NoCapture", [ParamTrait]>;
def ReadOnly : LlvmEnumAttributeTrait<"ReadOnly", [ParamTrait]>;

def NoUndef : LlvmEnumAttributeTrait<"NoUndef", [ParamTrait, RetTrait]>;
def NonNull : LlvmEnumAttributeTrait<"NonNull", [ParamTrait, RetTrait]>;


/// Represent the LLVM `memory(...)` attribute as the OR (or union) of memory
/// effects. An empty effects list means the operation does not access memory
Expand All @@ -356,7 +370,7 @@ def Speculatable : LlvmEnumAttributeTrait<"Speculatable">;
/// Example: `Memory<[(ref), (mod ArgMem, InaccessibleMem)]>` means the
/// operation may read from any kind of memory and write to argument and
/// inaccessible memory.
class Memory<list<dag> effects_> : Trait {
class Memory<list<dag> effects_> : Trait<[FnTrait]> {
list<dag> effects = effects_;
}

Expand Down Expand Up @@ -410,6 +424,8 @@ class Op<Dialect dialect_, string mnemonic_, list<Trait> traits_> {
dag arguments = ?;
dag results = ?;

list<dag> value_traits = [];

list<dag> verifier = [];

string summary = ?;
Expand Down
1 change: 1 addition & 0 deletions include/llvm-dialects/TableGen/Operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class Operation : public OperationBase {
std::string name;
std::string mnemonic;
std::vector<Trait *> traits;
std::map<llvm::StringRef, std::vector<Trait *>> value_traits;

std::vector<NamedValue> results;

Expand Down
23 changes: 23 additions & 0 deletions lib/TableGen/Operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,29 @@ bool Operation::parse(raw_ostream &errs, GenDialectsContext *context,
for (RecordTy *traitRec : record->getValueAsListOfDefs("traits"))
op->traits.push_back(context->getTrait(traitRec));

ListInit *List = record->getValueAsListInit("value_traits");
for (const Init *I : List->getValues()) {
if (const DagInit *DI = dyn_cast<DagInit>(I)) {
if (DI->getNumArgs() != 1) {
errs << "value_traits " << *DI << " is missing argument name";
return false;
}
StringRef name = DI->getArgNameStr(0);
std::vector<Trait*>& traits = op->value_traits[name];

if (const DefInit *Op = dyn_cast<DefInit>(DI->getOperator()))
traits.push_back(context->getTrait(Op->getDef()));
else {
errs << "value_traits " << *DI << " is not of form (Trait $arg)";
return false;
}
}
else {
errs << "value_traits was not a list of DAG's";
return false;
}
}

EvaluationPlanner evaluation(op->m_system);

for (const auto &arg : op->getFullArguments()) {
Expand Down
11 changes: 11 additions & 0 deletions test/unit/dialect/TestDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ def DialectOp4 : TestOp<"dialect.op.4", []> {
let summary = "Test operation 4";
}

def DialectOp5 : TestOp<"dialect.op.5", []> {
let results = (outs Ptr:$ptr);
let arguments = (ins Ptr:$result);

let value_traits = [
(ReadOnly $ptr),
(NoCapture $ptr),
(NonNull $result)
];
}

def InstNameConflictTestOp : Op<TestDialect, "try.conflict", [WillReturn]> {
let results = (outs);
let arguments = (ins value:$instName, value:$inst__name);
Expand Down
Loading