77// ===----------------------------------------------------------------------===//
88
99#include " CIRGenBuilder.h"
10+ #include " llvm/ADT/TypeSwitch.h"
1011
1112using namespace clang ::CIRGen;
1213
@@ -72,8 +73,6 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
7273 if (!offset)
7374 return ;
7475
75- mlir::Type subType;
76-
7776 auto getIndexAndNewOffset =
7877 [](int64_t offset, int64_t eltSize) -> std::pair<int64_t , int64_t > {
7978 int64_t divRet = offset / eltSize;
@@ -83,40 +82,49 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
8382 return {divRet, modRet};
8483 };
8584
86- if (auto arrayTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
87- int64_t eltSize = layout.getTypeAllocSize (arrayTy.getElementType ());
88- subType = arrayTy.getElementType ();
89- const auto [index, newOffset] = getIndexAndNewOffset (offset, eltSize);
90- indices.push_back (index);
91- offset = newOffset;
92- } else if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) {
93- auto elts = recordTy.getMembers ();
94- int64_t Pos = 0 ;
95- for (size_t i = 0 ; i < elts.size (); ++i) {
96- int64_t eltSize =
97- (int64_t )layout.getTypeAllocSize (elts[i]).getFixedValue ();
98- unsigned alignMask = layout.getABITypeAlign (elts[i]).value () - 1 ;
99- if (recordTy.getPacked ())
100- alignMask = 0 ;
101- // Union's fields have the same offset, so no need to change Pos here,
102- // we just need to find EltSize that is greater then the required offset.
103- // The same is true for the similar union type check below
104- if (!recordTy.isUnion ())
105- Pos = (Pos + alignMask) & ~alignMask;
106- assert (offset >= 0 );
107- if (offset < Pos + eltSize) {
108- indices.push_back (i);
109- subType = elts[i];
110- offset -= Pos;
111- break ;
112- }
113- // No need to update Pos here, see the comment above.
114- if (!recordTy.isUnion ())
115- Pos += eltSize;
116- }
117- } else {
118- llvm_unreachable (" unexpected type" );
119- }
85+ mlir::Type subType =
86+ llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)
87+ .Case <cir::ArrayType>([&](auto arrayTy) {
88+ int64_t eltSize = layout.getTypeAllocSize (arrayTy.getElementType ());
89+ const auto [index, newOffset] =
90+ getIndexAndNewOffset (offset, eltSize);
91+ indices.push_back (index);
92+ offset = newOffset;
93+ return arrayTy.getElementType ();
94+ })
95+ .Case <cir::RecordType>([&](auto recordTy) {
96+ ArrayRef<mlir::Type> elts = recordTy.getMembers ();
97+ int64_t pos = 0 ;
98+ for (size_t i = 0 ; i < elts.size (); ++i) {
99+ int64_t eltSize =
100+ (int64_t )layout.getTypeAllocSize (elts[i]).getFixedValue ();
101+ unsigned alignMask = layout.getABITypeAlign (elts[i]).value () - 1 ;
102+ if (recordTy.getPacked ())
103+ alignMask = 0 ;
104+ // Union's fields have the same offset, so no need to change pos
105+ // here, we just need to find eltSize that is greater then the
106+ // required offset. The same is true for the similar union type
107+ // check below
108+ if (!recordTy.isUnion ())
109+ pos = (pos + alignMask) & ~alignMask;
110+ assert (offset >= 0 );
111+ if (offset < pos + eltSize) {
112+ indices.push_back (i);
113+ offset -= pos;
114+ return elts[i];
115+ }
116+ // No need to update pos here, see the comment above.
117+ if (!recordTy.isUnion ())
118+ pos += eltSize;
119+ }
120+ llvm_unreachable (" offset was not found within the record" );
121+ })
122+ .Default ([](mlir::Type otherTy) {
123+ llvm_unreachable (" unexpected type" );
124+ return otherTy; // Even though this is unreachable, we need to
125+ // return a type to satisfy the return type of the
126+ // lambda.
127+ });
120128
121129 assert (subType);
122130 computeGlobalViewIndicesFromFlatOffset (offset, subType, layout, indices);
0 commit comments