xref: /llvm-project/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td (revision e887f8290df419ffd4e018b6f8afbaeb1912cf0e)
1//===-- LLVMOpBase.td - LLVM IR dialect shared definitions -*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains shared definitions for the LLVM IR dialect and its
10// subdialects.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVMIR_OP_BASE
15#define LLVMIR_OP_BASE
16
17include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
18include "mlir/Dialect/LLVMIR/LLVMInterfaces.td"
19include "mlir/IR/OpBase.td"
20include "mlir/Interfaces/SideEffectInterfaces.td"
21
22//===----------------------------------------------------------------------===//
23// LLVM dialect type constraints.
24//===----------------------------------------------------------------------===//
25
26// LLVM dialect type.
27def LLVM_Type : DialectType<LLVM_Dialect,
28                            CPred<"::mlir::LLVM::isCompatibleOuterType($_self)">,
29                            "LLVM dialect-compatible type">;
30
31// Type constraint accepting LLVM token type.
32def LLVM_TokenType : Type<
33  CPred<"::llvm::isa<::mlir::LLVM::LLVMTokenType>($_self)">,
34  "LLVM token type">,
35  BuildableType<"::mlir::LLVM::LLVMTokenType::get($_builder.getContext())">;
36
37// Type constraint accepting LLVM primitive types, i.e. all types except void
38// and function.
39def LLVM_PrimitiveType : Type<
40  And<[LLVM_Type.predicate,
41       CPred<"!::llvm::isa<::mlir::LLVM::LLVMVoidType, "
42                         "::mlir::LLVM::LLVMFunctionType>($_self)">]>,
43  "primitive LLVM type">;
44
45// Type constraint accepting any LLVM function type.
46def LLVM_FunctionType : Type<CPred<"::llvm::isa<::mlir::LLVM::LLVMFunctionType>($_self)">,
47                         "LLVM function type", "::mlir::LLVM::LLVMFunctionType">;
48
49// Type constraint accepting any LLVM floating point type.
50def LLVM_AnyFloat : Type<
51  CPred<"::mlir::LLVM::isCompatibleFloatingPointType($_self)">,
52  "floating point LLVM type">;
53
54// Type constraint accepting any LLVM pointer type.
55def LLVM_AnyPointer : Type<CPred<"::llvm::isa<::mlir::LLVM::LLVMPointerType>($_self)">,
56                          "LLVM pointer type", "::mlir::LLVM::LLVMPointerType">;
57
58// Pointer in a given address space.
59class LLVM_PointerInAddressSpace<int addressSpace> : Type<
60  And<[LLVM_AnyPointer.predicate,
61      CPred<
62        "::llvm::cast<::mlir::LLVM::LLVMPointerType>($_self).getAddressSpace() == "
63        # addressSpace>]>,
64  "LLVM pointer in address space " # addressSpace,
65  "::mlir::LLVM::LLVMPointerType"> {
66  let builderCall = "$_builder.getType<::mlir::LLVM::LLVMPointerType>("
67    # addressSpace # ")";
68}
69
70// Type constraint accepting an LLVM pointer type in address space 0.
71def LLVM_DefaultPointer : LLVM_PointerInAddressSpace<0>;
72
73// Type constraint accepting any LLVM structure type.
74def LLVM_AnyStruct : Type<CPred<"::llvm::isa<::mlir::LLVM::LLVMStructType>($_self)">,
75                         "LLVM structure type">;
76
77// Type constraint accepting opaque LLVM structure type.
78def LLVM_OpaqueStruct : Type<
79  And<[LLVM_AnyStruct.predicate,
80       CPred<"::llvm::cast<::mlir::LLVM::LLVMStructType>($_self).isOpaque()">]>>;
81
82// Type constraint accepting any LLVM target extension type.
83def LLVM_AnyTargetExt : Type<CPred<"::llvm::isa<::mlir::LLVM::LLVMTargetExtType>($_self)">,
84                            "LLVM target extension type">;
85
86// Type constraint accepting LLVM target extension types with no support for
87// memory operations such as alloca, load and store.
88def LLVM_NonLoadableTargetExtType : Type<
89  And<[LLVM_AnyTargetExt.predicate,
90        CPred<"!::llvm::cast<::mlir::LLVM::LLVMTargetExtType>($_self).supportsMemOps()">]
91        >>;
92
93// Type constraint accepting any LLVM type that can be loaded or stored, i.e. a
94// type that has size (not void, function, opaque struct type or target
95// extension type which does not support memory operations).
96def LLVM_LoadableType : Type<
97  Or<[And<[LLVM_PrimitiveType.predicate, Neg<LLVM_OpaqueStruct.predicate>,
98          Neg<LLVM_NonLoadableTargetExtType.predicate>]>,
99      LLVM_PointerElementTypeInterface.predicate]>,
100  "LLVM type with size">;
101
102// Type constraint accepting any LLVM aggregate type, i.e. structure or array.
103def LLVM_AnyAggregate : Type<
104  CPred<"::llvm::isa<::mlir::LLVM::LLVMStructType, "
105                   "::mlir::LLVM::LLVMArrayType>($_self)">,
106  "LLVM aggregate type">;
107
108// Type constraint accepting any LLVM non-aggregate type, i.e. not structure or
109// array.
110def LLVM_AnyNonAggregate : Type<And<[LLVM_Type.predicate,
111                                     Neg<LLVM_AnyAggregate.predicate>]>,
112                               "LLVM-compatible non-aggregate type">;
113
114// Type constraint accepting any LLVM vector type.
115def LLVM_AnyVector : Type<CPred<"::mlir::LLVM::isCompatibleVectorType($_self)">,
116                         "LLVM dialect-compatible vector type">;
117
118// Type constraint accepting any LLVM fixed-length vector type.
119def LLVM_AnyFixedVector : Type<CPred<
120                                "!::mlir::LLVM::isScalableVectorType($_self)">,
121                                "LLVM dialect-compatible fixed-length vector type">;
122
123// Type constraint accepting any LLVM scalable vector type.
124def LLVM_AnyScalableVector : Type<CPred<
125                                "::mlir::LLVM::isScalableVectorType($_self)">,
126                                "LLVM dialect-compatible scalable vector type">;
127
128// Type constraint accepting an LLVM vector type with an additional constraint
129// on the vector element type.
130class LLVM_VectorOf<Type element> : Type<
131  And<[LLVM_AnyVector.predicate,
132       SubstLeaves<
133         "$_self",
134         "::mlir::LLVM::getVectorElementType($_self)",
135         element.predicate>]>,
136  "LLVM dialect-compatible vector of " # element.summary>;
137
138// Type constraint accepting a constrained type, or a vector of such types.
139class LLVM_ScalarOrVectorOf<Type element> :
140    AnyTypeOf<[element, LLVM_VectorOf<element>]>;
141
142// Base class for LLVM operations. Defines the interface to the llvm::IRBuilder
143// used to translate to proper LLVM IR and the interface to the mlir::OpBuilder
144// used to import from LLVM IR.
145class LLVM_OpBase<Dialect dialect, string mnemonic, list<Trait> traits = []> :
146    Op<dialect, mnemonic, traits> {
147  // A pattern for constructing the LLVM IR Instruction (or other Value) that
148  // corresponds to this op.  This pattern can use `builder` to refer to an
149  // `llvm::IRBuilder<>` instance, $-names of arguments and results and the
150  // following special variable names:
151  //   - $_resultType - substituted with the LLVM IR type of the result;
152  //   - $_numOperands - substituted with the number of operands (including
153  //                     the variadic ones);
154  //   - $_hasResult - substituted with a check that a variadic-result op does
155  //                   have a result (LLVM ops can have 0 or 1 result);
156  //   - $_location - mlir::Location object of the instruction.
157  // Additionally, `$$` can be used to produce the dollar character.
158  string llvmBuilder = "";
159
160  // A builder to construct the MLIR LLVM dialect operation given the matching
161  // LLVM IR instruction `inst` and its operands `llvmOperands`. The
162  // following $-variables exist:
163  //   - $name - substituted by the remapped `inst` operand value at the index
164  //             of the MLIR operation argument with the given name, or if the
165  //             name matches the result name, by a reference to store the
166  //             result of the newly created MLIR operation to;
167  //   - $_op - substituted by a reference to store the newly created MLIR
168  //            operation (only for MLIR operations that return no result);
169  //   - $_int_attr - substituted by a call to an integer attribute matcher;
170  //   - $_float_attr - substituted by a call to a float attribute matcher;
171  //   - $_var_attr - substituted by a call to a variable attribute matcher;
172  //   - $_label_attr - substituted by a call to a label attribute matcher;
173  //   - $_roundingMode_attr - substituted by a call to a rounding mode
174  //     attribute matcher;
175  //   - $_fpExceptionBehavior_attr - substituted by a call to a FP exception
176  //     behavior attribute matcher;
177  //   - $_resultType - substituted with the MLIR result type;
178  //   - $_location - substituted with the MLIR location;
179  //   - $_builder - substituted with the MLIR builder;
180  //   - $_qualCppClassName - substitiuted with the MLIR operation class name.
181  // Always either store a reference to the result of the newly created
182  // operation, or to the operation itself if it does not return a result.
183  // Additionally, `$$` can be used to produce the dollar character.
184  string mlirBuilder = "";
185
186  // An array that specifies a mapping from MLIR argument indices to LLVM IR
187  // operand indices. The mapping is necessary since argument and operand
188  // indices do not always match. If not defined, the array is set to the
189  // identity permutation. An operation may define any custom index permutation
190  // and set a specific argument index to -1 if it does not map to an LLVM IR
191  // operand.
192  list<int> llvmArgIndices = [];
193}
194
195//===----------------------------------------------------------------------===//
196// Patterns for LLVM dialect operations.
197//===----------------------------------------------------------------------===//
198
199// Patterns with code to set flags and metadata of memory operations after their
200// translation to LLVM IR instructions. Operations may use the patterns to
201// implement their "llvmBuilder". The patterns assume the `op` and `inst`
202// variables exist and refer to the original MLIR operation and the translated
203// LLVM IR instruction, respectively.
204class LLVM_MemOpPatterns {
205  code setAlignmentCode = [{
206    if ($alignment.has_value()) {
207      auto align = *$alignment;
208      if (align != 0)
209        inst->setAlignment(llvm::Align(align));
210    }
211  }];
212  code setVolatileCode = [{
213    inst->setVolatile($volatile_);
214  }];
215  code setSyncScopeCode = [{
216    if ($syncscope.has_value()) {
217      llvm::LLVMContext &llvmContext = builder.getContext();
218      inst->setSyncScopeID(llvmContext.getOrInsertSyncScopeID(*$syncscope));
219    }
220  }];
221  code setOrderingCode = [{
222    inst->setAtomic(convertAtomicOrderingToLLVM($ordering));
223  }];
224  code setNonTemporalMetadataCode = [{
225    if ($nontemporal) {
226      llvm::MDNode *metadata = llvm::MDNode::get(
227          inst->getContext(), llvm::ConstantAsMetadata::get(
228              builder.getInt32(1)));
229      inst->setMetadata(llvm::LLVMContext::MD_nontemporal, metadata);
230    }
231  }];
232  code setInvariantGroupCode = [{
233    if ($invariantGroup) {
234      llvm::MDNode *metadata = llvm::MDNode::get(inst->getContext(),
235                                                 std::nullopt);
236      inst->setMetadata(llvm::LLVMContext::MD_invariant_group, metadata);
237    }
238  }];
239  code setAccessGroupsMetadataCode = [{
240    moduleTranslation.setAccessGroupsMetadata(op, inst);
241  }];
242  code setAliasAnalysisMetadataCode = [{
243    moduleTranslation.setAliasScopeMetadata(op, inst);
244    moduleTranslation.setTBAAMetadata(op, inst);
245  }];
246}
247
248//===----------------------------------------------------------------------===//
249// Base classes for LLVM dialect operations.
250//===----------------------------------------------------------------------===//
251
252// Base class for LLVM operations. All operations get an "llvm." prefix in
253// their name automatically and should either have zero or one result.
254class LLVM_Op<string mnemonic, list<Trait> traits = []> :
255    LLVM_OpBase<LLVM_Dialect, mnemonic, traits>;
256
257// Base class for LLVM memory access operations that implement the access group
258// and alias analysis interfaces. The "aliasAttrs" list contains the arguments
259// required by the access group and alias analysis interfaces. Derived
260// operations should append the "aliasAttrs" to their argument list.
261class LLVM_MemAccessOpBase<string mnemonic, list<Trait> traits = []> :
262    LLVM_Op<mnemonic, !listconcat([
263      DeclareOpInterfaceMethods<AccessGroupOpInterface>,
264      DeclareOpInterfaceMethods<AliasAnalysisOpInterface>], traits)>,
265    LLVM_MemOpPatterns {
266  dag aliasAttrs = (ins OptionalAttr<LLVM_AccessGroupArrayAttr>:$access_groups,
267                    OptionalAttr<LLVM_AliasScopeArrayAttr>:$alias_scopes,
268                    OptionalAttr<LLVM_AliasScopeArrayAttr>:$noalias_scopes,
269                    OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa);
270}
271
272// Base class for LLVM intrinsics operation. It is similar to LLVM_Op, but
273// provides the "llvmBuilder" field for constructing the intrinsic.
274// The builder relies on the contents of "overloadedResults" and
275// "overloadedOperands" lists that contain the positions of intrinsic results
276// and operands that are overloadable in the LLVM sense, that is their types
277// must be passed in during the construction of the intrinsic declaration to
278// differentiate between differently-typed versions of the intrinsic.
279// If the intrinsic has multiple results, this will eventually be packed into a
280// single struct result. In this case, the types of any overloaded results need
281// to be accessed via the LLVMStructType, instead of directly via the result.
282// "opName" contains the name of the operation to be associated with the
283// intrinsic and "enumName" contains the name of the intrinsic as appears in
284// `llvm::Intrinsic` enum; one usually wants these to be related. Additionally,
285// the base class also defines the "mlirBuilder" field to support the inverse
286// translation starting from an LLVM IR intrinsic. The "requiresAccessGroup",
287// "requiresAliasAnalysis", and "requiresFastmath" flags specify which
288// interfaces the intrinsic implements. If the corresponding flags are set, the
289// "aliasAttrs" list contains the arguments required by the access group and
290// alias analysis interfaces. Derived intrinsics should append the "aliasAttrs"
291// to their argument list if they set one of the flags. LLVM `immargs` can be
292// represented as MLIR attributes by providing both the `immArgPositions` and
293// `immArgAttrNames` lists. These two lists should have equal length, with
294// `immArgPositions` containing the argument positions on the LLVM IR attribute
295// that are `immargs`, and `immArgAttrNames` mapping these to corresponding
296// MLIR attributes.
297class LLVM_IntrOpBase<Dialect dialect, string opName, string enumName,
298                      list<int> overloadedResults, list<int> overloadedOperands,
299                      list<Trait> traits, int numResults,
300                      bit requiresAccessGroup = 0, bit requiresAliasAnalysis = 0,
301                      bit requiresFastmath = 0, bit requiresOpBundles = 0,
302                      list<int> immArgPositions = [],
303                      list<string> immArgAttrNames = []>
304    : LLVM_OpBase<dialect, opName, !listconcat(
305        !if(!gt(requiresAccessGroup, 0),
306            [DeclareOpInterfaceMethods<AccessGroupOpInterface>], []),
307        !if(!gt(requiresAliasAnalysis, 0),
308            [DeclareOpInterfaceMethods<AliasAnalysisOpInterface>], []),
309        !if(!gt(requiresFastmath, 0),
310            [DeclareOpInterfaceMethods<FastmathFlagsInterface>], []),
311        traits)>,
312      LLVM_MemOpPatterns,
313      Results<!if(!gt(numResults, 0), (outs LLVM_Type:$res), (outs))> {
314  dag aliasAttrs = !con(
315        !if(!gt(requiresAccessGroup, 0),
316            (ins OptionalAttr<LLVM_AccessGroupArrayAttr>:$access_groups),
317            (ins )),
318        !if(!gt(requiresAliasAnalysis, 0),
319            (ins OptionalAttr<LLVM_AliasScopeArrayAttr>:$alias_scopes,
320                 OptionalAttr<LLVM_AliasScopeArrayAttr>:$noalias_scopes,
321                 OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa),
322            (ins )));
323  dag opBundleArgs = !if(!gt(requiresOpBundles, 0),
324                         (ins VariadicOfVariadic<LLVM_Type,
325                                "op_bundle_sizes">:$op_bundle_operands,
326                              DenseI32ArrayAttr:$op_bundle_sizes,
327                              OptionalAttr<ArrayAttr>:$op_bundle_tags),
328                         (ins ));
329  string llvmEnumName = enumName;
330  string overloadedResultsCpp =  "{" # !interleave(overloadedResults, ", ") # "}";
331  string overloadedOperandsCpp =  "{" # !interleave(overloadedOperands, ", ") # "}";
332  string immArgPositionsCpp = "{" # !interleave(immArgPositions, ", ") # "}";
333  string immArgAttrNamesCpp = "{" # !interleave(!foreach(name, immArgAttrNames,
334    "StringLiteral(\"" # name # "\")"), ", ") # "}";
335  string baseLlvmBuilder = [{
336    auto *inst = LLVM::detail::createIntrinsicCall(
337      builder, moduleTranslation, &opInst, llvm::Intrinsic::}] # !interleave([
338        enumName, "" # numResults, overloadedResultsCpp, overloadedOperandsCpp,
339        immArgPositionsCpp, immArgAttrNamesCpp], ",") # [{);
340    (void) inst;
341    }];
342  string baseLlvmBuilderCoda = !if(!gt(numResults, 0), "$res = inst;", "");
343  let llvmBuilder =  baseLlvmBuilder # !if(!gt(requiresAccessGroup, 0), setAccessGroupsMetadataCode, "")
344       # !if(!gt(requiresAliasAnalysis, 0), setAliasAnalysisMetadataCode, "")
345       # baseLlvmBuilderCoda;
346
347  string baseMlirBuilder = [{
348    SmallVector<Value> mlirOperands;
349    SmallVector<NamedAttribute> mlirAttrs;
350    if (failed(moduleImport.convertIntrinsicArguments(
351      llvmOperands,
352      llvmOpBundles,
353      }] # !if(!gt(requiresOpBundles, 0), "true", "false") # [{,
354      }] # immArgPositionsCpp # [{,
355      }] # immArgAttrNamesCpp # [{,
356      mlirOperands,
357      mlirAttrs))
358    ) {
359      return failure();
360    }
361    SmallVector<Type> resultTypes =
362    }] # !if(!gt(numResults, 0), "{$_resultType};", "{};") # [{
363    auto op = $_builder.create<$_qualCppClassName>(
364      $_location, resultTypes, mlirOperands, mlirAttrs);
365    }];
366  string baseMlirBuilderCoda = !if(!gt(numResults, 0), "$res = op;", "$_op = op;");
367  let mlirBuilder = baseMlirBuilder # !if(!gt(requiresFastmath, 0),
368      "moduleImport.setFastmathFlagsAttr(inst, op);", "")
369    # baseMlirBuilderCoda;
370
371  // Code for handling a `range` attribute that holds the constant range of the
372  // intrinsic's result (if one is specified at the call site). This is intended
373  // for GPU IDs and other calls where range() is meaningful. It expects
374  // an optional LLVM_ConstantRangeAttr named `range` to be present on the
375  // operation. These are included to abstract out common code in several
376  // dialects.
377  string setRangeRetAttrCode = [{
378    if ($range) {
379      inst->addRangeRetAttr(::llvm::ConstantRange(
380        $range->getLower(), $range->getUpper()));
381    }
382  }];
383  string importRangeRetAttrCode = [{
384    // Note: we don't want to look in to the declaration here.
385    auto rangeAttr = inst->getAttributes().getRetAttr(::llvm::Attribute::Range);
386    if (rangeAttr.isValid()) {
387      const ::llvm::ConstantRange& value = rangeAttr.getValueAsConstantRange();
388      op.setRangeAttr(::mlir::LLVM::ConstantRangeAttr::get($_builder.getContext(), value.getLower(), value.getUpper()));
389    }
390  }];
391}
392
393// Base class for LLVM intrinsic operations, should not be used directly. Places
394// the intrinsic into the LLVM dialect and prefixes its name with "intr.".
395class LLVM_IntrOp<string mnem, list<int> overloadedResults,
396                  list<int> overloadedOperands, list<Trait> traits,
397                  int numResults, bit requiresAccessGroup = 0,
398                  bit requiresAliasAnalysis = 0, bit requiresFastmath = 0,
399                  bit requiresOpBundles = 0,
400                  list<int> immArgPositions = [],
401                  list<string> immArgAttrNames = []>
402    : LLVM_IntrOpBase<LLVM_Dialect, "intr." # mnem, !subst(".", "_", mnem),
403                      overloadedResults, overloadedOperands, traits,
404                      numResults, requiresAccessGroup, requiresAliasAnalysis,
405                      requiresFastmath, requiresOpBundles, immArgPositions,
406                      immArgAttrNames>;
407
408// Base class for LLVM intrinsic operations returning no results. Places the
409// intrinsic into the LLVM dialect and prefixes its name with "intr.".
410//
411// Sample use: derive an entry from this class and populate the fields.
412//
413//    def LLVM_Name : LLVM_ZeroResultIntrOp<"name", [0], [Pure]>,
414//                    Arguments<(ins LLVM_Type, LLVM_Type)>;
415//
416// The mnemonic will be prefixed with "llvm.intr.", where the "llvm." part comes
417// from the LLVM dialect. The overloadedOperands list contains the indices of
418// the operands the type of which will be passed in the LLVM IR intrinsic
419// builder. In the example above, the Op has two arguments, but only the first
420// one (as indicated by `[0]`) is necessary to resolve the overloaded intrinsic.
421// The Op has no results.
422class LLVM_ZeroResultIntrOp<string mnem, list<int> overloadedOperands = [],
423                            list<Trait> traits = [],
424                            bit requiresAccessGroup = 0,
425                            bit requiresAliasAnalysis = 0,
426                            bit requiresOpBundles = 0,
427                            list<int> immArgPositions = [],
428                            list<string> immArgAttrNames = []>
429    : LLVM_IntrOp<mnem, [], overloadedOperands, traits, /*numResults=*/0,
430                  requiresAccessGroup, requiresAliasAnalysis,
431                  /*requiresFastMath=*/0, requiresOpBundles, immArgPositions,
432                  immArgAttrNames>;
433
434// Base class for LLVM intrinsic operations returning one result. Places the
435// intrinsic into the LLVM dialect and prefixes its name with "intr.". This is
436// similar to LLVM_ZeroResultIntrOp but allows one to define Ops returning one
437// result, called "res". Additionally, the overloadedResults list should contain
438// "0" if the result must be used to resolve overloaded intrinsics, or remain
439// empty otherwise.
440class LLVM_OneResultIntrOp<string mnem, list<int> overloadedResults = [],
441                           list<int> overloadedOperands = [],
442                           list<Trait> traits = [],
443                           bit requiresFastmath = 0,
444                           list<int> immArgPositions = [],
445                           list<string> immArgAttrNames = []>
446    : LLVM_IntrOp<mnem, overloadedResults, overloadedOperands, traits, 1,
447                  /*requiresAccessGroup=*/0, /*requiresAliasAnalysis=*/0,
448                  requiresFastmath, /*requiresOpBundles=*/0, immArgPositions,
449                  immArgAttrNames>;
450
451def LLVM_OneResultOpBuilder :
452  OpBuilder<(ins "Type":$resultType, "ValueRange":$operands,
453    CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes),
454  [{
455    if (resultType) $_state.addTypes(resultType);
456    $_state.addOperands(operands);
457    for (auto namedAttr : attributes)
458      $_state.addAttribute(namedAttr.getName(), namedAttr.getValue());
459  }]>;
460
461def LLVM_ZeroResultOpBuilder :
462  OpBuilder<(ins "ValueRange":$operands,
463    CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes),
464  [{
465    $_state.addOperands(operands);
466    for (auto namedAttr : attributes)
467      $_state.addAttribute(namedAttr.getName(), namedAttr.getValue());
468  }]>;
469
470// Compatibility builder that takes an instance of wrapped llvm::VoidType
471// to indicate no result.
472def LLVM_VoidResultTypeOpBuilder :
473  OpBuilder<(ins "Type":$resultType, "ValueRange":$operands,
474    CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes),
475  [{
476    assert(isCompatibleType(resultType) && "result must be an LLVM type");
477    assert(::llvm::isa<LLVMVoidType>(resultType) &&
478           "for zero-result operands, only 'void' is accepted as result type");
479    build($_builder, $_state, operands, attributes);
480  }]>;
481
482
483// Opaque builder used for terminator operations that contain successors.
484def LLVM_TerminatorPassthroughOpBuilder :
485  OpBuilder<(ins "ValueRange":$operands, "SuccessorRange":$destinations,
486    CArg<"ArrayRef<NamedAttribute>", "{}">:$attributes),
487  [{
488    $_state.addOperands(operands);
489    $_state.addSuccessors(destinations);
490    $_state.addAttributes(attributes);
491  }]>;
492
493
494#endif  // LLVMIR_OP_BASE
495