[clang] [CIR] Upstream ArraySubscriptExpr for fixed size array (PR #134536)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 8 12:46:59 PDT 2025
================
@@ -232,6 +233,152 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
llvm_unreachable("Unknown unary operator kind!");
}
+/// If the specified expr is a simple decay from an array to pointer,
+/// return the array subexpression.
+/// FIXME: this could be abstracted into a common AST helper.
+static const Expr *getSimpleArrayDecayOperand(const Expr *e) {
+ // If this isn't just an array->pointer decay, bail out.
+ const auto *castExpr = dyn_cast<CastExpr>(e);
+ if (!castExpr || castExpr->getCastKind() != CK_ArrayToPointerDecay)
+ return nullptr;
+
+ // If this is a decay from variable width array, bail out.
+ const Expr *subExpr = castExpr->getSubExpr();
+ if (subExpr->getType()->isVariableArrayType())
+ return nullptr;
+
+ return subExpr;
+}
+
+static mlir::IntegerAttr getConstantIndexOrNull(mlir::Value idx) {
+ // TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?
+ if (auto constantOp = dyn_cast<cir::ConstantOp>(idx.getDefiningOp()))
+ return mlir::dyn_cast<mlir::IntegerAttr>(constantOp.getValue());
+ return {};
+}
+
+static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,
+ CharUnits eltSize) {
+ // If we have a constant index, we can use the exact offset of the
+ // element we're accessing.
+ const mlir::IntegerAttr constantIdx = getConstantIndexOrNull(idx);
+ if (constantIdx) {
+ const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;
+ return arrayAlign.alignmentAtOffset(offset);
+ }
+ // Otherwise, use the worst-case alignment for any element.
+ return arrayAlign.alignmentOfArrayElement(eltSize);
+}
+
+static QualType getFixedSizeElementType(const ASTContext &astContext,
+ const VariableArrayType *vla) {
+ QualType eltType;
+ do {
+ eltType = vla->getElementType();
+ } while ((vla = astContext.getAsVariableArrayType(eltType)));
+ return eltType;
+}
+
+static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf,
+ mlir::Location beginLoc,
+ mlir::Location endLoc, mlir::Value ptr,
+ mlir::Type eltTy, mlir::Value idx,
+ bool inbounds, bool signedIndices,
+ bool shouldDecay) {
+ CIRGenModule &cgm = cgf.getCIRGenModule();
+ // TODO(cir): LLVM codegen emits in bound gep check here, is there anything
+ // that would enhance tracking this later in CIR?
+ if (inbounds)
+ assert(!cir::MissingFeatures::emitCheckedInBoundsGEP() && "NYI");
+ return cgm.getBuilder().getArrayElement(beginLoc, endLoc, ptr, eltTy, idx,
+ shouldDecay);
+}
+
+static Address
+emitArraySubscriptPtr(CIRGenFunction &cgf, mlir::Location beginLoc,
+ mlir::Location endLoc, Address addr, QualType eltType,
+ mlir::Value idx, bool inbounds, mlir::Location loc,
+ bool shouldDecay, QualType *arrayType, const Expr *base) {
+
+ // Determine the element size of the statically-sized base. This is
+ // the thing that the indices are expressed in terms of.
+ if (const VariableArrayType *vla =
+ cgf.getContext().getAsVariableArrayType(eltType)) {
+ eltType = getFixedSizeElementType(cgf.getContext(), vla);
+ }
+
+ // We can use that to compute the best alignment of the element.
+ const CharUnits eltSize = cgf.getContext().getTypeSizeInChars(eltType);
+ const CharUnits eltAlign =
+ getArrayElementAlign(addr.getAlignment(), idx, eltSize);
+
+ mlir::Value eltPtr;
+ const mlir::IntegerAttr index = getConstantIndexOrNull(idx);
+ if (!index) {
----------------
AmrDeveloper wrote:
Not sure if I can easily add MissingFeatures without conflict with the else branch, maybe I should upstream the basic implementation of this failed and function with errorNYI in their cases
https://github.com/llvm/llvm-project/pull/134536
More information about the cfe-commits
mailing list