@@ -232,6 +232,100 @@ def CIR_CastOp : CIR_Op<"cast", [
232232  }];
233233}
234234
235+ //===----------------------------------------------------------------------===//
236+ // DynamicCastOp
237+ //===----------------------------------------------------------------------===//
238+ 
239+ def CIR_DynamicCastKind : CIR_I32EnumAttr<
240+   "DynamicCastKind", "dynamic cast kind", [
241+     I32EnumAttrCase<"Ptr", 0, "ptr">,
242+     I32EnumAttrCase<"Ref", 1, "ref">
243+ ]>;
244+ 
245+ def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
246+   let summary = "Perform dynamic cast on record pointers";
247+   let description = [{
248+     The `cir.dyn_cast` operation models part of the semantics of the
249+     `dynamic_cast` operator in C++. It can be used to perform 3 kinds of casts
250+     on record pointers:
251+ 
252+     - Down-cast, which casts a base class pointer to a derived class pointer;
253+     - Side-cast, which casts a class pointer to a sibling class pointer;
254+     - Cast-to-complete, which casts a class pointer to a void pointer.
255+ 
256+     The input of the operation must be a record pointer. The result of the
257+     operation is either a record pointer or a void pointer.
258+ 
259+     The parameter `kind` specifies the semantics of this operation. If its value
260+     is `ptr`, then the operation models dynamic casts on pointers. Otherwise, if
261+     its value is `ref`, the operation models dynamic casts on references.
262+     Specifically:
263+ 
264+     - When the input pointer is a null pointer value:
265+       - If `kind` is `ref`, the operation will invoke undefined behavior. A
266+         sanitizer check will be emitted if sanitizer is on.
267+       - Otherwise, the operation will return a null pointer value as its result.
268+     - When the runtime type check fails:
269+       - If `kind` is `ref`, the operation will throw a `bad_cast` exception.
270+       - Otherwise, the operation will return a null pointer value as its result.
271+ 
272+     The `info` argument gives detailed information about the requested dynamic
273+     cast operation. It is an optional `#cir.dyn_cast_info` attribute that is
274+     only present when the operation models a down-cast or a side-cast.
275+ 
276+     The `relative_layout` argument specifies whether the Itanium C++ ABI vtable
277+     uses relative layout. It is only meaningful when the operation models a
278+     cast-to-complete operation.
279+ 
280+     Examples:
281+ 
282+     ```mlir
283+     %0 = cir.dyn_cast ptr %p : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
284+     %1 = cir.dyn_cast ptr relative_layout %p : !cir.ptr<!rec_Base>
285+               -> !cir.ptr<!rec_Derived>
286+     %2 = cir.dyn_cast ref %r : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
287+               #cir.dyn_cast_info<
288+                 #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>,
289+                 #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>,
290+                 @__dynamic_cast,
291+                 @__cxa_bad_cast,
292+                 #cir.int<0> : !s64i
293+               >
294+     ```
295+   }];
296+ 
297+   let arguments = (ins
298+     CIR_DynamicCastKind:$kind,
299+     CIR_PtrToRecordType:$src,
300+     OptionalAttr<CIR_DynamicCastInfoAttr>:$info,
301+     UnitAttr:$relative_layout
302+   );
303+ 
304+   let results = (outs
305+     CIR_PtrToAnyOf<[CIR_VoidType, CIR_RecordType]>:$result
306+   );
307+ 
308+   let assemblyFormat = [{
309+     $kind (`relative_layout` $relative_layout^)? $src
310+     `:` qualified(type($src)) `->` qualified(type($result))
311+     (qualified($info)^)? attr-dict
312+   }];
313+ 
314+   let extraClassDeclaration = [{
315+     /// Determine whether this operation models reference casting in C++.
316+     bool isRefcast() {
317+       return getKind() == ::cir::DynamicCastKind::Ref;
318+     }
319+ 
320+     /// Determine whether this operation represents a dynamic cast to a void
321+     /// pointer.
322+     bool isCastToVoid() {
323+       return getType().isVoidPtr();
324+     }
325+   }];
326+ 
327+   let hasLLVMLowering = false;
328+ }
235329
236330//===----------------------------------------------------------------------===//
237331// PtrStrideOp
0 commit comments