@@ -232,6 +232,100 @@ def CIR_CastOp : CIR_Op<"cast", [
232
232
}];
233
233
}
234
234
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
+ srcRtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>,
289
+ destRtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>,
290
+ runtimeFunc = @__dynamic_cast,
291
+ badCastFunc = @__cxa_bad_cast,
292
+ offsetHint = #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
+ }
235
329
236
330
//===----------------------------------------------------------------------===//
237
331
// PtrStrideOp
0 commit comments