@@ -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,94 @@ 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+ // TODO: OpenACC: It isn't clear that stride would ever be anything other
200+ // than '1'? We emit the type of the reference 'correctly' as far as I
201+ // know, so it should just be 1 element each time. We could perhaps use
202+ // the 'inBytes' variant here, but it isn't clear what value that gets us.
203+ // We might need to revisit this once we try to opt this and see what is
204+ // going to happen.
205+ mlir::Value stride = createConstantInt (boundLoc, 64 , 1 );
206+
207+ auto bound = builder.create <mlir::acc::DataBoundsOp>(boundLoc, lowerBound,
208+ upperBound);
209+ bound.getStartIdxMutable ().assign (startIdx);
210+ if (extent)
211+ bound.getExtentMutable ().assign (extent);
212+ bound.getStrideMutable ().assign (stride);
213+
214+ return bound;
215+ }
216+
189217 // A helper function that gets the information from an operand to a data
190218 // clause, so that it can be used to emit the data operations.
191- inline DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk,
192- const Expr *e) {
219+ DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk, const Expr *e) {
193220 // TODO: OpenACC: Cache was different enough as to need a separate
194221 // `ActOnCacheVar`, so we are going to need to do some investigations here
195222 // when it comes to implement this for cache.
196223 if (dk == OpenACCDirectiveKind::Cache) {
197224 cgf.cgm .errorNYI (e->getSourceRange (),
198225 " OpenACC data operand for 'cache' directive" );
199- return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}};
226+ return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}, {} };
200227 }
201228
202229 const Expr *curVarExpr = e->IgnoreParenImpCasts ();
203230
204231 mlir::Location exprLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
232+ llvm::SmallVector<mlir::Value> bounds;
233+
234+ // Assemble the list of bounds.
235+ while (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
236+ mlir::Location boundLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
237+ mlir::Value lowerBound;
238+ mlir::Value upperBound;
239+ mlir::Value extent;
240+
241+ if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) {
242+ if (const Expr *lb = section->getLowerBound ())
243+ lowerBound = emitIntExpr (lb);
244+ else
245+ lowerBound = createConstantInt (boundLoc, 64 , 0 );
246+
247+ if (const Expr *len = section->getLength ()) {
248+ extent = emitIntExpr (len);
249+ } else {
250+ QualType baseTy = ArraySectionExpr::getBaseOriginalType (
251+ section->getBase ()->IgnoreParenImpCasts ());
252+ // We know this is the case as implicit lengths are only allowed for
253+ // array types with a constant size, or a dependent size. AND since
254+ // we are codegen we know we're not dependent.
255+ auto *arrayTy = cgf.getContext ().getAsConstantArrayType (baseTy);
256+ // Rather than trying to calculate the extent based on the
257+ // lower-bound, we can just emit this as an upper bound.
258+ upperBound =
259+ createConstantInt (boundLoc, 64 , arrayTy->getLimitedSize () - 1 );
260+ }
205261
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, {}, {}};
262+ curVarExpr = section->getBase ()->IgnoreParenImpCasts ();
263+ } else {
264+ const auto *subscript = dyn_cast<ArraySubscriptExpr>(curVarExpr);
265+
266+ lowerBound = emitIntExpr (subscript->getIdx ());
267+ // Length of an array index is always 1.
268+ extent = createConstantInt (boundLoc, 64 , 1 );
269+ curVarExpr = subscript->getBase ()->IgnoreParenImpCasts ();
270+ }
271+
272+ bounds.push_back (createBound (boundLoc, lowerBound, upperBound, extent));
211273 }
212274
213275 // TODO: OpenACC: if this is a member expr, emit the VarPtrPtr correctly.
214276 if (isa<MemberExpr>(curVarExpr)) {
215277 cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
216278 " OpenACC Data clause member expr" );
217- return {exprLoc, {}, {}};
279+ return {exprLoc, {}, {}, std::move (bounds) };
218280 }
219281
220282 // Sema has made sure that only 4 types of things can get here, array
@@ -223,14 +285,14 @@ class OpenACCClauseCIREmitter final
223285 // right.
224286 const auto *dre = cast<DeclRefExpr>(curVarExpr);
225287 const auto *vd = cast<VarDecl>(dre->getFoundDecl ()->getCanonicalDecl ());
226- return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName ()};
288+ return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName (),
289+ std::move (bounds)};
227290 }
228291
229292 template <typename BeforeOpTy, typename AfterOpTy>
230293 void addDataOperand (const Expr *varOperand, mlir::acc::DataClause dataClause,
231294 bool structured, bool implicit) {
232295 DataOperandInfo opInfo = getDataOperandInfo (dirKind, varOperand);
233- mlir::ValueRange bounds;
234296
235297 // TODO: OpenACC: we should comprehend the 'modifier-list' here for the data
236298 // operand. At the moment, we don't have a uniform way to assign these
@@ -239,7 +301,7 @@ class OpenACCClauseCIREmitter final
239301
240302 auto beforeOp =
241303 builder.create <BeforeOpTy>(opInfo.beginLoc , opInfo.varValue , structured,
242- implicit, opInfo.name , bounds);
304+ implicit, opInfo.name , opInfo. bounds );
243305 operation.getDataClauseOperandsMutable ().append (beforeOp.getResult ());
244306
245307 AfterOpTy afterOp;
@@ -248,7 +310,7 @@ class OpenACCClauseCIREmitter final
248310 builder.setInsertionPointAfter (operation);
249311 afterOp = builder.create <AfterOpTy>(opInfo.beginLoc , beforeOp.getResult (),
250312 opInfo.varValue , structured, implicit,
251- opInfo.name , bounds);
313+ opInfo.name , opInfo. bounds );
252314 }
253315
254316 // Set the 'rest' of the info for both operations.
0 commit comments