diff --git a/include/llvm-dialects/Dialect/Dialect.td b/include/llvm-dialects/Dialect/Dialect.td index 55557a7..3859952 100644 --- a/include/llvm-dialects/Dialect/Dialect.td +++ b/include/llvm-dialects/Dialect/Dialect.td @@ -320,29 +320,43 @@ multiclass AttrEnum { /// Traits generally map to llvm::Attributes. // ============================================================================ -class Trait; +class TraitProperty; +def FnTrait : TraitProperty; +def ParamTrait : TraitProperty; +def RetTrait : TraitProperty; -class LlvmEnumAttributeTrait : Trait { +class Trait P>{ + list Properties = P; +} + +class LlvmEnumAttributeTrait P> : Trait

{ 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 @@ -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 effects_> : Trait { +class Memory effects_> : Trait<[FnTrait]> { list effects = effects_; } @@ -410,6 +424,8 @@ class Op traits_> { dag arguments = ?; dag results = ?; + list value_traits = []; + list verifier = []; string summary = ?; diff --git a/include/llvm-dialects/TableGen/Operations.h b/include/llvm-dialects/TableGen/Operations.h index ae725d4..68a2a88 100644 --- a/include/llvm-dialects/TableGen/Operations.h +++ b/include/llvm-dialects/TableGen/Operations.h @@ -102,6 +102,7 @@ class Operation : public OperationBase { std::string name; std::string mnemonic; std::vector traits; + std::map> value_traits; std::vector results; diff --git a/lib/TableGen/Operations.cpp b/lib/TableGen/Operations.cpp index d9c5ded..90a24a7 100644 --- a/lib/TableGen/Operations.cpp +++ b/lib/TableGen/Operations.cpp @@ -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(I)) { + if (DI->getNumArgs() != 1) { + errs << "value_traits " << *DI << " is missing argument name"; + return false; + } + StringRef name = DI->getArgNameStr(0); + std::vector& traits = op->value_traits[name]; + + if (const DefInit *Op = dyn_cast(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()) { diff --git a/test/unit/dialect/TestDialect.td b/test/unit/dialect/TestDialect.td index b22c36e..f3c8881 100644 --- a/test/unit/dialect/TestDialect.td +++ b/test/unit/dialect/TestDialect.td @@ -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 { let results = (outs); let arguments = (ins value:$instName, value:$inst__name);