@@ -392,12 +392,29 @@ class OpenACCClauseCIREmitter final
392392 CIRGenFunction::AutoVarEmission tempDeclEmission,
393393 mlir::acc::FirstprivateRecipeOp recipe, const VarDecl *varRecipe,
394394 const VarDecl *temporary) {
395- builder.createBlock (&recipe.getCopyRegion (), recipe.getCopyRegion ().end (),
396- {mainOp.getType (), mainOp.getType ()}, {loc, loc});
395+ mlir::Block *block = builder.createBlock (
396+ &recipe.getCopyRegion (), recipe.getCopyRegion ().end (),
397+ {mainOp.getType (), mainOp.getType ()}, {loc, loc});
397398 builder.setInsertionPointToEnd (&recipe.getCopyRegion ().back ());
398399
399- // TODO: OpenACC: Implement this copy to actually do something.
400+ mlir::BlockArgument fromArg = block->getArgument (0 );
401+ mlir::BlockArgument toArg = block->getArgument (1 );
402+
403+ mlir::Type elementTy =
404+ mlir::cast<cir::PointerType>(mainOp.getType ()).getPointee ();
405+
406+ // Set the address of the emission to be the argument, so that we initialize
407+ // that instead of the variable in the other block.
408+ tempDeclEmission.setAllocatedAddress (
409+ Address{toArg, elementTy, cgf.getContext ().getDeclAlign (varRecipe)});
410+ tempDeclEmission.EmittedAsOffload = true ;
411+
412+ CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, temporary};
413+ cgf.setAddrOfLocalVar (
414+ temporary,
415+ Address{fromArg, elementTy, cgf.getContext ().getDeclAlign (varRecipe)});
400416
417+ cgf.emitAutoVarInit (tempDeclEmission);
401418 mlir::acc::YieldOp::create (builder, locEnd);
402419 }
403420
@@ -417,6 +434,7 @@ class OpenACCClauseCIREmitter final
417434
418435 CIRGenFunction::AutoVarEmission tempDeclEmission{
419436 CIRGenFunction::AutoVarEmission::invalid ()};
437+ CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, varRecipe};
420438
421439 // Do the 'init' section of the recipe IR, which does an alloca, then the
422440 // initialization (except for firstprivate).
@@ -425,6 +443,7 @@ class OpenACCClauseCIREmitter final
425443 builder.setInsertionPointToEnd (&recipe.getInitRegion ().back ());
426444 tempDeclEmission =
427445 cgf.emitAutoVarAlloca (*varRecipe, builder.saveInsertionPoint ());
446+
428447 // 'firstprivate' doesn't do its initialization in the 'init' section,
429448 // instead does it in the 'copy' section. SO only do init here.
430449 // 'reduction' appears to use it too (rather than a 'copy' section), so
@@ -450,16 +469,19 @@ class OpenACCClauseCIREmitter final
450469 mlir::acc::YieldOp::create (builder, locEnd);
451470
452471 if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
453- // TODO: OpenACC: we should have a errorNYI call here if
454- // !varRecipe->getInit(), but as that generation isn't currently
455- // implemented, it ends up being too noisy. So when we implement copy-init
456- // generation both in Sema and here, we should have a diagnostic here.
472+ if (!varRecipe->getInit ()) {
473+ // If we don't have any initialization recipe, we failed during Sema to
474+ // initialize this correctly. If we disable the
475+ // Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
476+ // emit an error to tell us. However, emitting those errors during
477+ // production is a violation of the standard, so we cannot do them.
478+ cgf.cgm .errorNYI (
479+ exprRange, " firstprivate copy-init recipe not properly generated" );
480+ }
481+
457482 createFirstprivateRecipeCopy (loc, locEnd, mainOp, tempDeclEmission,
458483 recipe, varRecipe, temporary);
459484 }
460-
461- // Make sure we cleanup after ourselves here.
462- cgf.removeAddrOfLocalVar (varRecipe);
463485 }
464486
465487 void createRecipeDestroySection (mlir::Location loc, mlir::Location locEnd,
0 commit comments