// // This file is distributed under the MIT License. See LICENSE.md for details. // #ifndef MLIR_CLIFT_OPS #define MLIR_CLIFT_OPS include "mlir/Interfaces/CallInterfaces.td" include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/BuiltinAttributes.td" include "mlir/IR/FunctionInterfaces.td" include "mlir/IR/RegionKindInterface.td" include "mlir/IR/SymbolInterfaces.td" include "revng/Clift/CliftOpInterfaces.td" include "revng/Clift/CliftOpTraits.td" include "revng/Clift/CliftTypes.td" class Clift_Op traits = []> : Op; //===-------------------------- Type constraints --------------------------===// def Clift_AnyAddressableType : Type($_self)">, "value type">; def Clift_AnyObjectType : Type($_self)">, "object type">; def Clift_AnyValueType : Type($_self)">, "value type">; def Clift_AnyBooleanType : Type, "boolean type">; def Clift_AnyScalarType : Type, "scalar type">; def Clift_AnyIntegerType : Type($_self)">, "integer type">; def Clift_AnyPrimitiveIntegerType : Type($_self)">, "primitive integer type">; def Clift_AnyPointerType : Type($_self)">, "pointer type">; def Clift_AnyFunctionType : Type($_self)">, "function type">; def Clift_AnyNonVoidType : Type($_self)">, "non-void type">; class Clift_AnyNonConstType : Type]>, "non-const " # type.summary>; class Clift_AnyModifiableType : Type]>, "modifiable " # type.summary>; class Clift_AllTypesMatch names> : AllMatchSameOperatorTrait; class Clift_AllSizesMatch names> : AllMatchSameOperatorTrait; class Clift_AllPointeeTypesMatch names> : AllMatchSameOperatorTrait($_self.getType()).getPointeeType()", "pointee type">; class Clift_UnqualifiedTypeMatches : TypesMatchWith; class Clift_PointeeTypeMatches : TypesMatchWith($_self).getPointeeType()">; class Clift_LValueOperand : PredOpTrait<"operand " # name # " is an lvalue expression", CPred<"clift::isLvalueExpression($" # name # ")">>; //===---------------------------- Region types ----------------------------===// def Clift_StatementRegion : Region, "Region containing statements">; def Clift_ExpressionRegion : Region, "Region representing an expression">; def Clift_OptionalExpressionRegion : Region, "Optional region representing an expression">; //===------------------------ Top level operations ------------------------===// def Clift_FunctionOp : Clift_Op<"func", [Clift_GlobalOpInterface, CallableOpInterface, FunctionOpInterface, AutomaticAllocationScope, IsolatedFromAbove]> { let arguments = (ins StrAttr:$sym_name, TypeAttrOf:$type, OptionalAttr:$arg_attrs, OptionalAttr:$res_attrs, UnitAttr:$noreturn, UnitAttr:$always_inline, DefaultValuedStrAttr:$handle); let description = [{ expression. }]; let regions = (region Clift_StatementRegion:$body); let builders = [ OpBuilder<(ins "llvm::StringRef":$Name, "clift::FunctionType":$FunctionType)> ]; let hasCustomAssemblyFormat = 1; code extraClassDeclaration = [{ static mlir::StringAttr getFunctionTypeAttrName(mlir::OperationName Name) { return getTypeAttrName(Name); } mlir::StringAttr getFunctionTypeAttrName() { return getTypeAttrName(); } mlir::TypeAttr getFunctionTypeAttr() { return getTypeAttr(); } void setFunctionTypeAttr(mlir::TypeAttr Attr) { return setTypeAttr(Attr); } FunctionType getFunctionType() { return clift::unwrapped_cast(getType()); } mlir::Type getReturnType() { return getFunctionType().getReturnType(); } unsigned getArgCount() { return getFunctionType().getArgumentTypes().size(); } clift::AttrDictView getArgAttrs(unsigned Index) { std::optional Attrs = getArgAttrs(); mlir::DictionaryAttr DictAttr = Attrs ? mlir::cast((*Attrs)[Index]) : mlir::DictionaryAttr::get(getContext()); return AttrDictView(DictAttr); } clift::AttrDictView getResAttrs(unsigned Index) { std::optional Attrs = getArgAttrs(); mlir::DictionaryAttr DictAttr = Attrs ? mlir::cast((*Attrs)[Index]) : mlir::DictionaryAttr::get(getContext()); return AttrDictView(DictAttr); } mlir::Region::BlockListType& getBlocks() { return getBody().getBlocks(); } mlir::Block::args_iterator args_begin() { return getBody().front().args_begin(); } mlir::Block::args_iterator args_end() { return getBody().front().args_end(); } // Implementation of CallableOpInterface mlir::Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); } /// Returns the result types of this function. llvm::ArrayRef getCallableResults() { return getResultTypes(); } // Implementation of FunctionOpInterface llvm::ArrayRef getArgumentTypes(); llvm::ArrayRef getResultTypes(); mlir::Type cloneTypeWith(mlir::TypeRange inputs, mlir::TypeRange results); }]; } def Clift_GlobalVariableOp : Clift_Op<"global", [Clift_GlobalOpInterface, NoRegionArguments, IsolatedFromAbove]> { let arguments = (ins SymbolNameAttr:$sym_name, TypeAttrOf:$type, DefaultValuedStrAttr:$handle); let description = [{ global variable }]; let regions = (region Clift_OptionalExpressionRegion:$initializer); let assemblyFormat = [{ $sym_name `:` $type (`=` $initializer^)? attr-dict-with-keyword }]; let hasVerifier = 1; } //===----------------------------- Statements -----------------------------===// class Clift_BasicStatementOp traits = []> : Clift_Op; class Clift_StatementOp traits = []> : Clift_BasicStatementOp; class Clift_JumpStatementOp : Clift_BasicStatementOp; // Two bit integer used to represent two flags, each indicating the presence of // the break and continue label assignments respectively. def LoopLabelMaskAttr : TypedUnsignedIntegerAttrBase, "uint8_t", "Loop label mask">; class Clift_LoopStatementOp traits = []> : Clift_BasicStatementOp { let arguments = (ins LoopLabelMaskAttr:$label_mask, Variadic:$labels); // The generation of default builders for loop operations is skipped to avoid // mistakes, as building a valid loop with explicit label mask and operands // would be error prone. let skipDefaultBuilders = 1; let builders = [ OpBuilder<(ins CArg<"clift::LoopOpInterface", "{}">:$OtherLoop)> ]; } def Clift_MakeLabelOp : Clift_StatementOp<"make_label"> { let arguments = (ins DefaultValuedStrAttr:$name, DefaultValuedStrAttr:$handle); let results = (outs Clift_LabelType:$result); let assemblyFormat = [{ attr-dict }]; let hasCanonicalizeMethod = 1; let hasVerifier = 1; let builders = [ OpBuilder<(ins), [{ build($_builder, $_state, clift::LabelType::get($_builder.getContext())); }]> ]; let extraClassDeclaration = [{ [[nodiscard]] LabelAssignmentOpInterface getAssignment(); }]; } def Clift_AssignLabelOp : Clift_BasicStatementOp<"assign_label", Clift_LabelAssignmentOpInterface> { let arguments = (ins Clift_LabelType:$label); let assemblyFormat = [{ $label attr-dict }]; let extraClassDeclaration = [{ [[nodiscard]] MakeLabelOp getLabelOp(); unsigned getAssignedLabelCount() { return 1; } mlir::Value getAssignedLabel(unsigned Index) { revng_assert(Index == 0); return getLabel(); } }]; } def Clift_BlockStatementOp : Clift_StatementOp<"block", [Clift_StatementRegionOpInterface]> { let regions = (region Clift_StatementRegion:$block); let assemblyFormat = [{ $block attr-dict-with-keyword }]; let extraClassDeclaration = [{ bool isIndirectlyNoFallthrough(); unsigned getStatementRegionCount() { return 1; } mlir::Region &getStatementRegion(unsigned Index) { revng_assert(Index == 0); return getBlock(); } }]; } def Clift_BreakToOp : Clift_JumpStatementOp<"break_to"> { let arguments = (ins Clift_LabelType:$label); let assemblyFormat = [{ $label attr-dict }]; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] MakeLabelOp getLabelOp(); }]; } def Clift_ContinueToOp : Clift_JumpStatementOp<"continue_to"> { let arguments = (ins Clift_LabelType:$label); let assemblyFormat = [{ $label attr-dict }]; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] MakeLabelOp getLabelOp(); }]; } def Clift_DoWhileOp : Clift_LoopStatementOp<"do_while", [NoRegionArguments]> { let regions = (region Clift_StatementRegion:$body, Clift_ExpressionRegion:$condition); let assemblyFormat = [{ custom($label_mask, $labels) `body` $body `cond` $condition attr-dict-with-keyword }]; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] bool isBooleanTestedExpression(mlir::Region &R) { return &R == &getCondition(); } unsigned getStatementRegionCount() { return 1; } mlir::Region &getStatementRegion(unsigned Index) { revng_assert(Index == 0); return getBody(); } unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getCondition(); } }]; } def Clift_ExpressionStatementOp : Clift_StatementOp<"expr", [Clift_ExpressionRegionOpInterface]> { let regions = (region Clift_OptionalExpressionRegion:$expression); let assemblyFormat = [{ $expression attr-dict-with-keyword }]; let extraClassDeclaration = [{ [[nodiscard]] bool isDiscardedExpression(mlir::Region &R) { return true; } unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getExpression(); } }]; } def Clift_ForOp : Clift_LoopStatementOp<"for"> { let regions = (region Clift_StatementRegion:$initializer, Clift_OptionalExpressionRegion:$condition, Clift_OptionalExpressionRegion:$expression, Clift_StatementRegion:$body); let hasCustomAssemblyFormat = 1; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] bool isDiscardedExpression(mlir::Region &R); [[nodiscard]] bool isBooleanTestedExpression(mlir::Region &R) { return &R == &getCondition(); } unsigned getStatementRegionCount() { return 1; } mlir::Region &getStatementRegion(unsigned Index) { revng_assert(Index == 0); return getBody(); } unsigned getExpressionRegionCount(); mlir::Region &getExpressionRegion(unsigned Index); }]; } def Clift_GotoOp : Clift_JumpStatementOp<"goto"> { let arguments = (ins Clift_LabelType:$label); let assemblyFormat = [{ $label attr-dict }]; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] MakeLabelOp getLabelOp(); }]; } def Clift_IfOp : Clift_BasicStatementOp<"if", Clift_BranchOpInterface> { let regions = (region Clift_ExpressionRegion:$condition, Clift_StatementRegion:$then, Clift_StatementRegion:$else); let assemblyFormat = [{ $condition `then` $then (`else` $else^)? attr-dict-with-keyword }]; let hasVerifier = 1; let extraClassDeclaration = [{ bool isIndirectlyNoFallthrough() const; [[nodiscard]] bool isBooleanTestedExpression(mlir::Region &R) { return &R == &getCondition(); } unsigned getStatementRegionCount() { return 2; } mlir::Region &getStatementRegion(unsigned Index) { revng_assert(Index < 2); return Index == 0 ? getThen() : getElse(); } unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getCondition(); } }]; } def Clift_LocalVariableOp : Clift_StatementOp<"local"> { let arguments = (ins DefaultValuedStrAttr:$name, DefaultValuedStrAttr:$handle); let results = (outs Clift_AnyObjectType:$result); let regions = (region Clift_OptionalExpressionRegion:$initializer); let assemblyFormat = [{ `:` type($result) (`=` $initializer^)? attr-dict-with-keyword }]; let extraClassDeclaration = [{ mlir::Type getType() { return getResult().getType(); } unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getInitializer(); } }]; let hasVerifier = 1; } def Clift_ReturnOp : Clift_StatementOp<"return", [Clift_NoFallthrough]> { let regions = (region Clift_OptionalExpressionRegion:$result); let assemblyFormat = [{ $result attr-dict-with-keyword }]; let extraClassDeclaration = [{ unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getResult(); } }]; let hasVerifier = 1; } def Clift_RequireOp : Clift_StatementOp<"require"> { let arguments = (ins AnyType:$local); let assemblyFormat = [{ $local attr-dict `:` type($local) }]; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] LocalVariableOp getLocalOp(); }]; } def Clift_SwitchOp : Clift_BasicStatementOp<"switch", Clift_BranchOpInterface> { let arguments = (ins DenseI64ArrayAttr:$case_values); let regions = (region Clift_ExpressionRegion:$condition, Clift_StatementRegion:$default, VariadicRegion:$cases); let hasCustomAssemblyFormat = 1; let hasVerifier = 1; let builders = [ OpBuilder<(ins "llvm::ArrayRef":$case_values)> ]; code extraClassDeclaration = [{ bool isIndirectlyNoFallthrough() const; [[nodiscard]] mlir::Type getConditionType(); [[nodiscard]] mlir::Region &getConditionRegion() { return getRegion(0); } [[nodiscard]] bool hasDefaultCase() { return not getDefaultCaseRegion().empty(); } [[nodiscard]] mlir::Region &getDefaultCaseRegion() { return getRegion(1); } [[nodiscard]] unsigned getNumCases() { return getNumRegions() - 2; } [[nodiscard]] uint64_t getCaseValue(const unsigned index) { return static_cast(getCaseValues()[index]); } [[nodiscard]] llvm::MutableArrayRef getCaseRegions() { return getOperation()->getRegions().drop_front(2); } [[nodiscard]] mlir::Region &getCaseRegion(const unsigned index) { return getCaseRegions()[index]; } [[nodiscard]] mlir::Region *findCaseRegion(const uint64_t value); unsigned getStatementRegionCount() { return getOperation()->getRegions().size() - 1; } mlir::Region &getStatementRegion(unsigned Index) { return getOperation()->getRegions()[Index + 1]; } unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getCondition(); } }]; } def Clift_WhileOp : Clift_LoopStatementOp<"while", [NoRegionArguments]> { let regions = (region Clift_ExpressionRegion:$condition, Clift_StatementRegion:$body); let assemblyFormat = [{ custom($label_mask, $labels) `cond` $condition `body` $body attr-dict-with-keyword }]; let hasVerifier = 1; let extraClassDeclaration = [{ [[nodiscard]] bool isBooleanTestedExpression(mlir::Region &R) { return &R == &getCondition(); } unsigned getStatementRegionCount() { return 1; } mlir::Region &getStatementRegion(unsigned Index) { revng_assert(Index == 0); return getBody(); } unsigned getExpressionRegionCount() { return 1; } mlir::Region &getExpressionRegion(unsigned Index) { revng_assert(Index == 0); return getCondition(); } }]; } //===----------------------------- Expressions ----------------------------===// class Clift_BasicExpressionOp traits = []> : Clift_Op; class Clift_ExpressionOp traits = []> : Clift_BasicExpressionOp; def Clift_UndefOp : Clift_ExpressionOp<"undef"> { let results = (outs Clift_AnyAddressableType:$result); let assemblyFormat = [{ attr-dict `:` type($result) }]; } def Clift_YieldOp : Clift_Op<"yield", [Clift_ExpressionOpInterface, Terminator, NoRegionArguments]> { let arguments = (ins Clift_AnyAddressableType:$value); let assemblyFormat = [{ $value attr-dict `:` type($value) }]; let extraClassDeclaration = [{ [[nodiscard]] bool isDiscardedOperand(mlir::OpOperand &Operand); [[nodiscard]] bool isBooleanTestedOperand(mlir::OpOperand &Operand); }]; } def Clift_ImmediateOp : Clift_ExpressionOp<"imm"> { let arguments = (ins I64Attr:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($result) }]; } def Clift_StringOp : Clift_ExpressionOp<"str"> { let arguments = (ins StrAttr:$value); let results = (outs AnyType:$result); let assemblyFormat = [{ $value attr-dict `:` type($result) }]; let hasVerifier = 1; } class Clift_UnaryArithmeticOp : Clift_ExpressionOp]> { let arguments = (ins Clift_AnyPrimitiveIntegerType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) }]; } class Clift_BinaryArithmeticOp traits = []> : Clift_ExpressionOp])> { let arguments = (ins Clift_AnyPrimitiveIntegerType:$lhs, Clift_AnyPrimitiveIntegerType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let builders = [ OpBuilder<(ins "mlir::Value":$Lhs, "mlir::Value":$Rhs), [{ build($_builder, $_state, Lhs.getType(), Lhs, Rhs); }]> ]; let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` custom(type($result), type($lhs), type($rhs)) }]; } class Clift_PointerArithmeticOp traits = []> : Clift_ExpressionOp { let arguments = (ins AnyType:$lhs, AnyType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` `(` custom(type($result), type($lhs), type($rhs)) `)` }]; let hasVerifier = 1; let extraClassDeclaration = [{ unsigned getPointerOperandIndex() { return clift::impl::getPointerArithmeticPointerOperandIndex(getOperation()); } mlir::Value getPointer() { return getOperation()->getOperand(getPointerOperandIndex()); } unsigned getOffsetOperandIndex() { return clift::impl::getPointerArithmeticOffsetOperandIndex(getOperation()); } mlir::Value getOffset() { return getOperation()->getOperand(getOffsetOperandIndex()); } }]; } class Clift_BinaryLogicalOp : Clift_ExpressionOp { let arguments = (ins Clift_AnyScalarType:$lhs, Clift_AnyScalarType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` custom(type($lhs), type($rhs)) `->` type($result) }]; let extraClassDeclaration = [{ [[nodiscard]] bool isBooleanTestedOperand(mlir::OpOperand &Operand) { return true; } }]; } class Clift_ShiftOp : Clift_ExpressionOp]> { let arguments = (ins Clift_AnyPrimitiveIntegerType:$lhs, Clift_AnyPrimitiveIntegerType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` custom(type($lhs), type($rhs)) }]; } class Clift_ComparisonOp : Clift_ExpressionOp]> { let arguments = (ins Clift_AnyScalarType:$lhs, Clift_AnyScalarType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` custom(type($lhs), type($rhs)) `->` type($result) }]; } class Clift_UnaryIntegerMutationOp : Clift_ExpressionOp, Clift_LValueOperand<"value">]> { let arguments = (ins Clift_AnyModifiableType:$value); let results = (outs Clift_AnyPrimitiveIntegerType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) }]; let extraClassDeclaration = [{ bool isLvalueExpression() { return true; } }]; } def Clift_NegOp : Clift_UnaryArithmeticOp<"neg">; def Clift_AddOp : Clift_BinaryArithmeticOp<"add", [Commutative]>; def Clift_SubOp : Clift_BinaryArithmeticOp<"sub">; def Clift_MulOp : Clift_BinaryArithmeticOp<"mul", [Commutative]>; def Clift_DivOp : Clift_BinaryArithmeticOp<"div">; def Clift_RemOp : Clift_BinaryArithmeticOp<"rem">; def Clift_PtrAddOp : Clift_PointerArithmeticOp<"ptr_add", [Commutative]>; def Clift_PtrSubOp : Clift_PointerArithmeticOp<"ptr_sub">; def Clift_PtrDiffOp : Clift_ExpressionOp<"ptr_diff"> { let arguments = (ins Clift_AnyPointerType:$lhs, Clift_AnyPointerType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` custom(type($lhs), type($rhs)) `->` type($result) }]; let hasVerifier = 1; } def Clift_LogicalNotOp : Clift_ExpressionOp<"not", [Clift_ReturnsBoolean]> { let arguments = (ins Clift_AnyIntegerType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) `->` type($result) }]; let extraClassDeclaration = [{ [[nodiscard]] bool isBooleanTestedOperand(mlir::OpOperand &Operand) { return true; } }]; } def Clift_LogicalAndOp : Clift_BinaryLogicalOp<"and">; def Clift_LogicalOrOp : Clift_BinaryLogicalOp<"or">; def Clift_BitwiseNotOp : Clift_UnaryArithmeticOp<"bitnot">; def Clift_BitwiseAndOp : Clift_BinaryArithmeticOp<"bitand", [Commutative]>; def Clift_BitwiseOrOp : Clift_BinaryArithmeticOp<"bitor", [Commutative]>; def Clift_BitwiseXorOp : Clift_BinaryArithmeticOp<"bitxor", [Commutative]>; def Clift_ShiftLeftOp : Clift_ShiftOp<"shl">; def Clift_ShiftRightOp : Clift_ShiftOp<"shr">; def Clift_CmpEqOp : Clift_ComparisonOp<"eq">; def Clift_CmpNeOp : Clift_ComparisonOp<"ne">; def Clift_CmpLtOp : Clift_ComparisonOp<"lt">; def Clift_CmpGtOp : Clift_ComparisonOp<"gt">; def Clift_CmpLeOp : Clift_ComparisonOp<"le">; def Clift_CmpGeOp : Clift_ComparisonOp<"ge">; def Clift_IncrementOp : Clift_UnaryIntegerMutationOp<"inc">; def Clift_DecrementOp : Clift_UnaryIntegerMutationOp<"dec">; def Clift_PostIncrementOp : Clift_UnaryIntegerMutationOp<"post_inc">; def Clift_PostDecrementOp : Clift_UnaryIntegerMutationOp<"post_dec">; class Clift_CastExpressionOp traits = []> : Clift_BasicExpressionOp; def Clift_DecayOp : Clift_CastExpressionOp<"decay"> { let arguments = (ins AnyType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) `->` type($result) }]; let hasVerifier = 1; } def Clift_BitCastOp : Clift_CastExpressionOp<"bitcast", [Clift_AllSizesMatch<["value", "result"]>]> { let arguments = (ins Clift_AnyValueType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) `->` type($result) }]; } def Clift_ExtendOp : Clift_CastExpressionOp<"extend"> { let arguments = (ins Clift_AnyIntegerType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) `->` type($result) }]; let hasVerifier = 1; } def Clift_TruncateOp : Clift_CastExpressionOp<"truncate"> { let arguments = (ins Clift_AnyIntegerType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) `->` type($result) }]; let hasVerifier = 1; } def Clift_PtrResizeOp : Clift_CastExpressionOp<"ptr_resize", [Clift_AllPointeeTypesMatch<["value", "result"]>]> { let arguments = (ins Clift_AnyPointerType:$value); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $value attr-dict `:` type($value) `->` type($result) }]; let hasVerifier = 1; } def Clift_AddressofOp : Clift_ExpressionOp<"addressof", [Clift_PointeeTypeMatches<"result", "object">, Clift_LValueOperand<"object">]> { let arguments = (ins AnyType:$object); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $object attr-dict `:` type($result) }]; } def Clift_IndirectionOp : Clift_ExpressionOp<"indirection", [Clift_PointeeTypeMatches<"pointer", "result">]> { let arguments = (ins Clift_AnyPointerType:$pointer); let results = (outs Clift_AnyNonVoidType:$result); let assemblyFormat = [{ $pointer attr-dict `:` type($pointer) }]; let extraClassDeclaration = [{ bool isLvalueExpression() { return true; } }]; } def Clift_AssignOp : Clift_ExpressionOp<"assign", [AllTypesMatch<["lhs", "result"]>, Clift_AllTypesMatch<["lhs", "rhs"]>, Clift_LValueOperand<"lhs">]> { let arguments = (ins Clift_AnyModifiableType:$lhs, AnyType:$rhs); let results = (outs AnyType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` custom(type($lhs), type($rhs)) }]; let extraClassDeclaration = [{ bool isLvalueExpression() { return true; } }]; } def Clift_AccessOp : Clift_ExpressionOp<"access"> { let arguments = (ins AnyType:$value, UnitAttr:$indirect, I64Attr:$member_index); let results = (outs AnyType:$result); let assemblyFormat = [{ `<` (`indirect` $indirect^)? $member_index `>` $value attr-dict `:` type($value) `->` type($result) }]; let extraClassDeclaration = [{ [[nodiscard]] bool isIndirect() { return getIndirect(); } [[nodiscard]] bool isLvalueExpression(); [[nodiscard]] clift::ClassType getClassType(); [[nodiscard]] clift::FieldAttr getFieldAttr(); }]; let hasVerifier = 1; } def Clift_SubscriptOp : Clift_ExpressionOp<"subscript", [Clift_PointeeTypeMatches<"pointer", "result">]> { let arguments = (ins AnyType:$pointer, Clift_AnyIntegerType:$index); let results = (outs AnyType:$result); let assemblyFormat = [{ $pointer `,` $index attr-dict `:` `(` type($pointer) `,` type($index) `)` }]; let extraClassDeclaration = [{ bool isLvalueExpression() { return true; } }]; let hasVerifier = 1; } def Clift_CommaOp : Clift_ExpressionOp<"comma", [AllTypesMatch<["rhs", "result"]>]> { let arguments = (ins Clift_AnyAddressableType:$lhs, Clift_AnyAddressableType:$rhs); let results = (outs AnyType:$result); let assemblyFormat = [{ $lhs `,` $rhs attr-dict `:` type($lhs) `,` type($rhs) }]; let extraClassDeclaration = [{ bool isLvalueExpression() { return clift::isLvalueExpression(getRhs()); } [[nodiscard]] bool isDiscardedOperand(mlir::OpOperand &Operand) { return &Operand == &getOperation()->getOpOperand(0); } }]; } def Clift_UseOp : Clift_ExpressionOp<"use", [DeclareOpInterfaceMethods]> { let arguments = (ins FlatSymbolRefAttr:$symbol_name); let results = (outs Clift_AnyAddressableType:$result); let assemblyFormat = [{ $symbol_name attr-dict `:` type($result) }]; let extraClassDeclaration = [{ bool isLvalueExpression() { return true; } }]; } def Clift_CallOp : Clift_ExpressionOp<"call"> { let arguments = (ins AnyType:$function, Variadic:$arguments); let results = (outs Clift_AnyNonConstType:$result); let hasCustomAssemblyFormat = 1; let hasVerifier = 1; let extraClassDeclaration = [{ FunctionType getFunctionType(); }]; } def Clift_TernaryOp : Clift_ExpressionOp<"ternary", [Clift_AllTypesMatch<["lhs", "rhs"]>, Clift_UnqualifiedTypeMatches<"lhs", "result">]> { let arguments = (ins Clift_AnyScalarType:$condition, AnyType:$lhs, AnyType:$rhs); let results = (outs Clift_AnyNonConstType:$result); let assemblyFormat = [{ $condition `,` $lhs `,` $rhs attr-dict `:` `(` custom(type($condition), type($lhs), type($rhs)) `)` }]; let extraClassDeclaration = [{ [[nodiscard]] bool isBooleanTestedOperand(mlir::OpOperand &Operand) { return &Operand == &getOperation()->getOpOperand(0); } }]; } def Clift_AggregateOp : Clift_ExpressionOp<"aggregate"> { let arguments = (ins Variadic:$initializers); let results = (outs Clift_AnyNonConstType:$result); let hasCustomAssemblyFormat = 1; let hasVerifier = 1; } #endif