@@ -121,6 +121,11 @@ class OpenACCClauseCIREmitter final
121121 return constOp.getResult ();
122122 }
123123
124+ mlir::Value createConstantInt (SourceLocation loc, unsigned width,
125+ int64_t value) {
126+ return createConstantInt (cgf.cgm .getLoc (loc), width, value);
127+ }
128+
124129 mlir::acc::DeviceType decodeDeviceType (const IdentifierInfo *ii) {
125130 // '*' case leaves no identifier-info, just a nullptr.
126131 if (!ii)
@@ -184,37 +189,89 @@ class OpenACCClauseCIREmitter final
184189 mlir::Location beginLoc;
185190 mlir::Value varValue;
186191 llvm::StringRef name;
192+ llvm::SmallVector<mlir::Value> bounds;
187193 };
188194
195+ mlir::Value createBound (mlir::Location boundLoc, mlir::Value lowerBound,
196+ mlir::Value upperBound, mlir::Value extent) {
197+ // Arrays always have a start-idx of 0.
198+ mlir::Value startIdx = createConstantInt (boundLoc, 64 , 0 );
199+ // Stride is always 1 in C/C++.
200+ mlir::Value stride = createConstantInt (boundLoc, 64 , 1 );
201+
202+ auto bound = builder.create <mlir::acc::DataBoundsOp>(boundLoc, lowerBound,
203+ upperBound);
204+ bound.getStartIdxMutable ().assign (startIdx);
205+ if (extent)
206+ bound.getExtentMutable ().assign (extent);
207+ bound.getStrideMutable ().assign (stride);
208+
209+ return bound;
210+ }
211+
189212 // A helper function that gets the information from an operand to a data
190213 // clause, so that it can be used to emit the data operations.
191- inline DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk,
192- const Expr *e) {
214+ DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk, const Expr *e) {
193215 // TODO: OpenACC: Cache was different enough as to need a separate
194216 // `ActOnCacheVar`, so we are going to need to do some investigations here
195217 // when it comes to implement this for cache.
196218 if (dk == OpenACCDirectiveKind::Cache) {
197219 cgf.cgm .errorNYI (e->getSourceRange (),
198220 " OpenACC data operand for 'cache' directive" );
199- return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}};
221+ return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}, {} };
200222 }
201223
202224 const Expr *curVarExpr = e->IgnoreParenImpCasts ();
203225
204226 mlir::Location exprLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
227+ llvm::SmallVector<mlir::Value> bounds;
228+
229+ // Assemble the list of bounds.
230+ while (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
231+ mlir::Location boundLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
232+ mlir::Value lowerBound;
233+ mlir::Value upperBound;
234+ mlir::Value extent;
235+
236+ if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) {
237+ if (const Expr *lb = section->getLowerBound ())
238+ lowerBound = emitIntExpr (lb);
239+ else
240+ lowerBound = createConstantInt (boundLoc, 64 , 0 );
241+
242+ if (const Expr *len = section->getLength ()) {
243+ extent = emitIntExpr (len);
244+ } else {
245+ QualType baseTy = ArraySectionExpr::getBaseOriginalType (
246+ section->getBase ()->IgnoreParenImpCasts ());
247+ // We know this is the case as implicit lengths are only allowed for
248+ // array types with a constant size, or a dependent size. AND since
249+ // we are codegen we know we're not dependent.
250+ auto *arrayTy = cgf.getContext ().getAsConstantArrayType (baseTy);
251+ // Rather than trying to calculate the extent based on the
252+ // lower-bound, we can just emit this as an upper bound.
253+ upperBound =
254+ createConstantInt (boundLoc, 64 , arrayTy->getLimitedSize () - 1 );
255+ }
205256
206- // TODO: OpenACC: Assemble the list of bounds.
207- if (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
208- cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
209- " OpenACC data clause array subscript/section" );
210- return {exprLoc, {}, {}};
257+ curVarExpr = section->getBase ()->IgnoreParenImpCasts ();
258+ } else {
259+ const auto *subscript = cast<ArraySubscriptExpr>(curVarExpr);
260+
261+ lowerBound = emitIntExpr (subscript->getIdx ());
262+ // Length of an array index is always 1.
263+ extent = createConstantInt (boundLoc, 64 , 1 );
264+ curVarExpr = subscript->getBase ()->IgnoreParenImpCasts ();
265+ }
266+
267+ bounds.push_back (createBound (boundLoc, lowerBound, upperBound, extent));
211268 }
212269
213270 // TODO: OpenACC: if this is a member expr, emit the VarPtrPtr correctly.
214271 if (isa<MemberExpr>(curVarExpr)) {
215272 cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
216273 " OpenACC Data clause member expr" );
217- return {exprLoc, {}, {}};
274+ return {exprLoc, {}, {}, std::move (bounds) };
218275 }
219276
220277 // Sema has made sure that only 4 types of things can get here, array
@@ -223,14 +280,14 @@ class OpenACCClauseCIREmitter final
223280 // right.
224281 const auto *dre = cast<DeclRefExpr>(curVarExpr);
225282 const auto *vd = cast<VarDecl>(dre->getFoundDecl ()->getCanonicalDecl ());
226- return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName ()};
283+ return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName (),
284+ std::move (bounds)};
227285 }
228286
229287 template <typename BeforeOpTy, typename AfterOpTy>
230288 void addDataOperand (const Expr *varOperand, mlir::acc::DataClause dataClause,
231289 bool structured, bool implicit) {
232290 DataOperandInfo opInfo = getDataOperandInfo (dirKind, varOperand);
233- mlir::ValueRange bounds;
234291
235292 // TODO: OpenACC: we should comprehend the 'modifier-list' here for the data
236293 // operand. At the moment, we don't have a uniform way to assign these
@@ -239,7 +296,7 @@ class OpenACCClauseCIREmitter final
239296
240297 auto beforeOp =
241298 builder.create <BeforeOpTy>(opInfo.beginLoc , opInfo.varValue , structured,
242- implicit, opInfo.name , bounds);
299+ implicit, opInfo.name , opInfo. bounds );
243300 operation.getDataClauseOperandsMutable ().append (beforeOp.getResult ());
244301
245302 AfterOpTy afterOp;
@@ -248,7 +305,7 @@ class OpenACCClauseCIREmitter final
248305 builder.setInsertionPointAfter (operation);
249306 afterOp = builder.create <AfterOpTy>(opInfo.beginLoc , beforeOp.getResult (),
250307 opInfo.varValue , structured, implicit,
251- opInfo.name , bounds);
308+ opInfo.name , opInfo. bounds );
252309 }
253310
254311 // Set the 'rest' of the info for both operations.
0 commit comments