@@ -357,15 +357,11 @@ class OpenACCClauseCIREmitter final
357357 }
358358
359359 template <typename RecipeTy>
360- RecipeTy getOrCreateRecipe (ASTContext &astCtx, const Expr *varRef,
361- const VarDecl *varRecipe, DeclContext *dc,
362- QualType baseType, mlir::Value mainOp) {
363- mlir::ModuleOp mod =
364- builder.getBlock ()->getParent ()->getParentOfType <mlir::ModuleOp>();
365-
360+ std::string getRecipeName (SourceRange loc, QualType baseType) {
366361 std::string recipeName;
367362 {
368363 llvm::raw_string_ostream stream (recipeName);
364+
369365 if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
370366 stream << " privatization_" ;
371367 } else if constexpr (std::is_same_v<RecipeTy,
@@ -375,84 +371,138 @@ class OpenACCClauseCIREmitter final
375371 } else if constexpr (std::is_same_v<RecipeTy,
376372 mlir::acc::ReductionRecipeOp>) {
377373 stream << " reduction_" ;
378- // We don't have the reduction operation here well enough to know how to
379- // spell this correctly (+ == 'add', etc), so when we implement
380- // 'reduction' we have to do that here.
381- cgf.cgm .errorNYI (varRef->getSourceRange (),
382- " OpeNACC reduction recipe creation" );
374+ // TODO: OpenACC: once we have this part implemented, we can remove the
375+ // SourceRange `loc` variable from this function. We don't have the
376+ // reduction operation here well enough to know how to spell this
377+ // correctly (+ == 'add', etc), so when we implement 'reduction' we have
378+ // to do that here.
379+ cgf.cgm .errorNYI (loc, " OpenACC reduction recipe name creation" );
383380 } else {
384381 static_assert (!sizeof (RecipeTy), " Unknown Recipe op kind" );
385382 }
386383
387384 MangleContext &mc = cgf.cgm .getCXXABI ().getMangleContext ();
388385 mc.mangleCanonicalTypeName (baseType, stream);
389386 }
387+ return recipeName;
388+ }
390389
391- if (auto recipe = mod.lookupSymbol <RecipeTy>(recipeName))
392- return recipe;
393-
394- mlir::Location loc = cgf.cgm .getLoc (varRef->getBeginLoc ());
395- mlir::Location locEnd = cgf.cgm .getLoc (varRef->getEndLoc ());
390+ // Create the 'init' section of the recipe, including the 'copy' section for
391+ // 'firstprivate'.
392+ template <typename RecipeTy>
393+ void createRecipeInitCopy (mlir::Location loc, mlir::Location locEnd,
394+ SourceRange exprRange, mlir::Value mainOp,
395+ RecipeTy recipe, const VarDecl *varRecipe,
396+ const VarDecl *temporary) {
397+ assert (varRecipe && " Required recipe variable not set?" );
398+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
399+ // We haven't implemented the 'init' recipe for Reduction yet, so NYI
400+ // it.
401+ cgf.cgm .errorNYI (exprRange, " OpenACC Reduction recipe init" );
402+ }
396403
397- mlir::OpBuilder modBuilder (mod.getBodyRegion ());
398- auto recipe =
399- RecipeTy::create (modBuilder, loc, recipeName, mainOp.getType ());
404+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
405+ // We haven't implemented the 'init'/copy recipe for firstprivate yet, so
406+ // NYI it.
407+ cgf.cgm .errorNYI (exprRange, " OpenACC firstprivate recipe init" );
408+ }
400409
401410 CIRGenFunction::AutoVarEmission tempDeclEmission{
402411 CIRGenFunction::AutoVarEmission::invalid ()};
403412
404- // Init section.
405- {
406- llvm::SmallVector<mlir::Type> argsTys{mainOp.getType ()};
407- llvm::SmallVector<mlir::Location> argsLocs{loc};
408- builder.createBlock (&recipe.getInitRegion (), recipe.getInitRegion ().end (),
409- argsTys, argsLocs);
410- builder.setInsertionPointToEnd (&recipe.getInitRegion ().back ());
411-
412- if constexpr (!std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
413- // We have only implemented 'init' for private, so make this NYI until
414- // we have explicitly implemented everything.
415- cgf.cgm .errorNYI (varRef->getSourceRange (),
416- " OpenACC non-private recipe init" );
413+ // Do the 'init' section of the recipe IR, which does an alloca, then the
414+ // initialization (except for firstprivate).
415+ builder.createBlock (&recipe.getInitRegion (), recipe.getInitRegion ().end (),
416+ {mainOp.getType ()}, {loc});
417+ builder.setInsertionPointToEnd (&recipe.getInitRegion ().back ());
418+ tempDeclEmission =
419+ cgf.emitAutoVarAlloca (*varRecipe, builder.saveInsertionPoint ());
420+ // 'firstprivate' doesn't do its initialization in the 'init' section,
421+ // instead does it in the 'copy' section. SO only do init here.
422+ // 'reduction' appears to use it too (rather than a 'copy' section), so
423+ // we probably have to do it here too, but we can do that when we get to
424+ // reduction implementation.
425+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
426+ // We are OK with no init for builtins, arrays of builtins, or pointers,
427+ // else we should NYI so we know to go look for these.
428+ if (!varRecipe->getType ()
429+ ->getPointeeOrArrayElementType ()
430+ ->isBuiltinType () &&
431+ !varRecipe->getType ()->isPointerType () && !varRecipe->getInit ()) {
432+ // If we don't have any initialization recipe, we failed during Sema to
433+ // initialize this correctly. If we disable the
434+ // Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
435+ // emit an error to tell us. However, emitting those errors during
436+ // production is a violation of the standard, so we cannot do them.
437+ cgf.cgm .errorNYI (exprRange, " private default-init recipe" );
417438 }
439+ cgf.emitAutoVarInit (tempDeclEmission);
440+ }
418441
419- if (varRecipe) {
420- tempDeclEmission =
421- cgf.emitAutoVarAlloca (*varRecipe, builder.saveInsertionPoint ());
422- cgf.emitAutoVarInit (tempDeclEmission);
442+ mlir::acc::YieldOp::create (builder, locEnd);
443+
444+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
445+ if (!varRecipe->getInit ()) {
446+ // If we don't have any initialization recipe, we failed during Sema to
447+ // initialize this correctly. If we disable the
448+ // Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
449+ // emit an error to tell us. However, emitting those errors during
450+ // production is a violation of the standard, so we cannot do them.
451+ cgf.cgm .errorNYI (
452+ exprRange, " firstprivate copy-init recipe not properly generated" );
423453 }
424454
425- mlir::acc::YieldOp::create (builder, locEnd );
455+ cgf. cgm . errorNYI (exprRange, " firstprivate copy section generation " );
426456 }
427457
428- // Copy section.
429- if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp> ||
430- std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
431- // TODO: OpenACC: 'private' doesn't emit this, but for the other two we
432- // have to figure out what 'copy' means here.
433- cgf.cgm .errorNYI (varRef->getSourceRange (),
434- " OpenACC record type privatization copy section" );
435- }
458+ // Make sure we cleanup after ourselves here.
459+ cgf.removeAddrOfLocalVar (varRecipe);
460+ }
436461
437- // Destroy section (doesn't currently exist).
438- if (varRecipe && varRecipe->needsDestruction (cgf.getContext ())) {
439- llvm::SmallVector<mlir::Type> argsTys{mainOp.getType ()};
440- llvm::SmallVector<mlir::Location> argsLocs{loc};
441- mlir::Block *block = builder.createBlock (&recipe.getDestroyRegion (),
442- recipe.getDestroyRegion ().end (),
443- argsTys, argsLocs);
444- builder.setInsertionPointToEnd (&recipe.getDestroyRegion ().back ());
445-
446- mlir::Type elementTy =
447- mlir::cast<cir::PointerType>(mainOp.getType ()).getPointee ();
448- Address addr{block->getArgument (0 ), elementTy,
449- cgf.getContext ().getDeclAlign (varRecipe)};
450- cgf.emitDestroy (addr, baseType,
451- cgf.getDestroyer (QualType::DK_cxx_destructor));
452-
453- mlir::acc::YieldOp::create (builder, locEnd);
454- }
462+ void createRecipeDestroySection (mlir::Location loc, mlir::Location locEnd,
463+ mlir::Value mainOp, CharUnits alignment,
464+ QualType baseType,
465+ mlir::Region &destroyRegion) {
466+ mlir::Block *block = builder.createBlock (
467+ &destroyRegion, destroyRegion.end (), {mainOp.getType ()}, {loc});
468+ builder.setInsertionPointToEnd (&destroyRegion.back ());
469+
470+ mlir::Type elementTy =
471+ mlir::cast<cir::PointerType>(mainOp.getType ()).getPointee ();
472+ Address addr{block->getArgument (0 ), elementTy, alignment};
473+ cgf.emitDestroy (addr, baseType,
474+ cgf.getDestroyer (QualType::DK_cxx_destructor));
475+
476+ mlir::acc::YieldOp::create (builder, locEnd);
477+ }
478+
479+ template <typename RecipeTy>
480+ RecipeTy getOrCreateRecipe (ASTContext &astCtx, const Expr *varRef,
481+ const VarDecl *varRecipe, const VarDecl *temporary,
482+ DeclContext *dc, QualType baseType,
483+ mlir::Value mainOp) {
484+ mlir::ModuleOp mod =
485+ builder.getBlock ()->getParent ()->getParentOfType <mlir::ModuleOp>();
486+
487+ std::string recipeName =
488+ getRecipeName<RecipeTy>(varRef->getSourceRange (), baseType);
489+ if (auto recipe = mod.lookupSymbol <RecipeTy>(recipeName))
490+ return recipe;
491+
492+ mlir::Location loc = cgf.cgm .getLoc (varRef->getBeginLoc ());
493+ mlir::Location locEnd = cgf.cgm .getLoc (varRef->getEndLoc ());
494+
495+ mlir::OpBuilder modBuilder (mod.getBodyRegion ());
496+ auto recipe =
497+ RecipeTy::create (modBuilder, loc, recipeName, mainOp.getType ());
498+
499+ createRecipeInitCopy (loc, locEnd, varRef->getSourceRange (), mainOp, recipe,
500+ varRecipe, temporary);
455501
502+ if (varRecipe && varRecipe->needsDestruction (cgf.getContext ()))
503+ createRecipeDestroySection (loc, locEnd, mainOp,
504+ cgf.getContext ().getDeclAlign (varRecipe),
505+ baseType, recipe.getDestroyRegion ());
456506 return recipe;
457507 }
458508
@@ -1088,7 +1138,7 @@ class OpenACCClauseCIREmitter final
10881138 {
10891139 mlir::OpBuilder::InsertionGuard guardCase (builder);
10901140 auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
1091- cgf.getContext (), varExpr, varRecipe,
1141+ cgf.getContext (), varExpr, varRecipe, /* temporary= */ nullptr ,
10921142 Decl::castToDeclContext (cgf.curFuncDecl ), opInfo.baseType ,
10931143 privateOp.getResult ());
10941144 // TODO: OpenACC: The dialect is going to change in the near future to
0 commit comments