@@ -379,13 +379,20 @@ def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
379379]> {
380380 let summary = "Provides constant access to a global address";
381381 let description = [{
382- Get constant address of global `symbol`. It provides a way to access globals
383- from other global and always produces a pointer.
382+ Get constant address of global `symbol` and optionally apply offsets to
383+ access existing subelements. It provides a way to access globals from other
384+ global and always produces a pointer.
384385
385386 The type of the input symbol can be different from `#cir.global_view`
386387 output type, since a given view of the global might require a static
387388 cast for initializing other globals.
388389
390+ A list of indices can be optionally passed and each element subsequently
391+ indexes underlying types. For `symbol` types like `!cir.array`
392+ and `!cir.record`, it leads to the constant address of sub-elements, while
393+ for `!cir.ptr`, an offset is applied. The first index is relative to the
394+ original symbol type, not the produced one.
395+
389396 The result type of this attribute may be an integer type. In such a case,
390397 the pointer to the referenced global is casted to an integer and this
391398 attribute represents the casted result.
@@ -396,23 +403,57 @@ def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
396403 cir.global external @s = @".str2": !cir.ptr<i8>
397404 cir.global external @x = #cir.global_view<@s> : !cir.ptr<i8>
398405 cir.global external @s_addr = #cir.global_view<@s> : !s64i
406+
407+ cir.global external @rgb = #cir.const_array<[0 : i8, -23 : i8, 33 : i8]
408+ : !cir.array<i8 x 3>>
409+ cir.global external @elt_ptr = #cir.global_view<@rgb, [1]> : !cir.ptr<i8>
410+ ```
411+
412+ Note, that unlike LLVM IR's gep instruction, CIR doesn't add the leading
413+ zero index when it's known to be constant zero, e.g. for pointers, i.e. we
414+ use indexes exactly to access sub elements or for the offset. The leading
415+ zero index is added later in the lowering.
416+
417+ Example:
418+ ```
419+ struct A {
420+ int a;
421+ };
422+
423+ struct B: virtual A {
424+ int b;
425+ };
426+ ```
427+ VTT for B in CIR:
428+ ```
429+ cir.global linkonce_odr @_ZTT1B = #cir.const_array<[
430+ #cir.global_view<@_ZTV1B, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>]>
431+ : !cir.array<!cir.ptr<!u8i> x 1>
432+ ```
433+ VTT for B in LLVM IR:
434+ ```
435+ @_ZTT1B = linkonce_odr global [1 x ptr] [ptr getelementptr inbounds
436+ ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 3)], align 8
399437 ```
400438 }];
401439
402440 let parameters = (ins AttributeSelfTypeParameter<"">:$type,
403- "mlir::FlatSymbolRefAttr":$symbol);
441+ "mlir::FlatSymbolRefAttr":$symbol,
442+ OptionalParameter<"mlir::ArrayAttr">:$indices);
404443
405444 let builders = [
406445 AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
407- "mlir::FlatSymbolRefAttr":$symbol), [{
408- return $_get(type.getContext(), type, symbol);
446+ "mlir::FlatSymbolRefAttr":$symbol,
447+ CArg<"mlir::ArrayAttr", "{}">:$indices), [{
448+ return $_get(type.getContext(), type, symbol, indices);
409449 }]>
410450 ];
411451
412452 // let genVerifyDecl = 1;
413453 let assemblyFormat = [{
414454 `<`
415455 $symbol
456+ (`,` $indices^)?
416457 `>`
417458 }];
418459}
0 commit comments