@@ -158,13 +158,63 @@ class ConstExprEmitter
158158
159159// TODO(cir): this can be shared with LLVM's codegen
160160static QualType getNonMemoryType (CIRGenModule &cgm, QualType type) {
161- if (auto at = type->getAs <AtomicType>()) {
161+ if (const auto * at = type->getAs <AtomicType>()) {
162162 return cgm.getASTContext ().getQualifiedType (at->getValueType (),
163163 type.getQualifiers ());
164164 }
165165 return type;
166166}
167167
168+ static mlir::Attribute
169+ emitArrayConstant (CIRGenModule &cgm, mlir::Type desiredType,
170+ mlir::Type commonElementType, unsigned arrayBound,
171+ SmallVectorImpl<mlir::TypedAttr> &elements,
172+ mlir::TypedAttr filler) {
173+ const CIRGenBuilderTy &builder = cgm.getBuilder ();
174+
175+ unsigned nonzeroLength = arrayBound;
176+ if (elements.size () < nonzeroLength && builder.isNullValue (filler))
177+ nonzeroLength = elements.size ();
178+
179+ if (nonzeroLength == elements.size ()) {
180+ while (nonzeroLength > 0 &&
181+ builder.isNullValue (elements[nonzeroLength - 1 ]))
182+ --nonzeroLength;
183+ }
184+
185+ if (nonzeroLength == 0 )
186+ return cir::ZeroAttr::get (builder.getContext (), desiredType);
187+
188+ const unsigned trailingZeroes = arrayBound - nonzeroLength;
189+
190+ // Add a zeroinitializer array filler if we have lots of trailing zeroes.
191+ if (trailingZeroes >= 8 ) {
192+ assert (elements.size () >= nonzeroLength &&
193+ " missing initializer for non-zero element" );
194+ } else if (elements.size () != arrayBound) {
195+ elements.resize (arrayBound, filler);
196+
197+ if (filler.getType () != commonElementType)
198+ commonElementType = {};
199+ }
200+
201+ if (commonElementType) {
202+ SmallVector<mlir::Attribute, 4 > eles;
203+ eles.reserve (elements.size ());
204+
205+ for (const auto &element : elements)
206+ eles.push_back (element);
207+
208+ return cir::ConstArrayAttr::get (
209+ cir::ArrayType::get (builder.getContext (), commonElementType,
210+ arrayBound),
211+ mlir::ArrayAttr::get (builder.getContext (), eles));
212+ }
213+
214+ cgm.errorNYI (" array with different type elements" );
215+ return {};
216+ }
217+
168218// ===----------------------------------------------------------------------===//
169219// ConstantEmitter
170220// ===----------------------------------------------------------------------===//
@@ -271,16 +321,57 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
271321 cgm.getASTContext ().getTargetInfo ().useFP16ConversionIntrinsics ()) {
272322 cgm.errorNYI (" ConstExprEmitter::tryEmitPrivate half" );
273323 return {};
274- } else {
275- mlir::Type ty = cgm.convertType (destType);
276- assert (mlir::isa<cir::CIRFPTypeInterface>(ty) &&
277- " expected floating-point type" );
278- return cgm.getBuilder ().getAttr <cir::FPAttr>(ty, init);
279324 }
325+
326+ mlir::Type ty = cgm.convertType (destType);
327+ assert (mlir::isa<cir::CIRFPTypeInterface>(ty) &&
328+ " expected floating-point type" );
329+ return cgm.getBuilder ().getAttr <cir::FPAttr>(ty, init);
280330 }
281331 case APValue::Array: {
282- cgm.errorNYI (" ConstExprEmitter::tryEmitPrivate array" );
283- return {};
332+ const ArrayType *arrayTy = cgm.getASTContext ().getAsArrayType (destType);
333+ const QualType arrayElementTy = arrayTy->getElementType ();
334+ const unsigned numElements = value.getArraySize ();
335+ const unsigned numInitElts = value.getArrayInitializedElts ();
336+
337+ mlir::Attribute filler;
338+ if (value.hasArrayFiller ()) {
339+ filler = tryEmitPrivate (value.getArrayFiller (), arrayElementTy);
340+ if (!filler)
341+ return {};
342+ }
343+
344+ SmallVector<mlir::TypedAttr, 16 > elements;
345+ if (filler && builder.isNullValue (filler))
346+ elements.reserve (numInitElts + 1 );
347+ else
348+ elements.reserve (numInitElts);
349+
350+ mlir::Type commonElementType;
351+ for (unsigned i = 0 ; i < numInitElts; ++i) {
352+ const APValue &arrayElement = value.getArrayInitializedElt (i);
353+ const mlir::Attribute element =
354+ tryEmitPrivateForMemory (arrayElement, arrayElementTy);
355+ if (!element)
356+ return {};
357+
358+ const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);
359+ if (i == 0 )
360+ commonElementType = elementTyped.getType ();
361+ else if (elementTyped.getType () != commonElementType) {
362+ commonElementType = {};
363+ }
364+
365+ elements.push_back (elementTyped);
366+ }
367+
368+ mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);
369+ if (filler && !typedFiller)
370+ cgm.errorNYI (" array filler should always be typed" );
371+
372+ mlir::Type desiredType = cgm.convertType (destType);
373+ return emitArrayConstant (cgm, desiredType, commonElementType, numElements,
374+ elements, typedFiller);
284375 }
285376 case APValue::Vector: {
286377 cgm.errorNYI (" ConstExprEmitter::tryEmitPrivate vector" );
@@ -290,9 +381,23 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
290381 cgm.errorNYI (" ConstExprEmitter::tryEmitPrivate member pointer" );
291382 return {};
292383 }
293- case APValue::LValue:
294- cgm.errorNYI (" ConstExprEmitter::tryEmitPrivate lvalue" );
384+ case APValue::LValue: {
385+
386+ if (value.getLValueBase ()) {
387+ cgm.errorNYI (" non-null pointer initialization" );
388+ } else {
389+
390+ mlir::Type desiredType = cgm.convertType (destType);
391+ if (const cir::PointerType ptrType =
392+ mlir::dyn_cast<cir::PointerType>(desiredType)) {
393+ return builder.getConstPtrAttr (ptrType,
394+ value.getLValueOffset ().getQuantity ());
395+ } else {
396+ llvm_unreachable (" non-pointer variable initialized with a pointer" );
397+ }
398+ }
295399 return {};
400+ }
296401 case APValue::Struct:
297402 case APValue::Union:
298403 cgm.errorNYI (" ConstExprEmitter::tryEmitPrivate struct or union" );
0 commit comments