15
15
#include " CIRGenCXXABI.h"
16
16
#include " CIRGenCstEmitter.h"
17
17
#include " CIRGenFunction.h"
18
+ #include " CIRGenOpenMPRuntime.h"
18
19
#include " CIRGenTypes.h"
19
20
#include " CIRGenValue.h"
20
21
#include " TargetInfo.h"
@@ -103,7 +104,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
103
104
codeGenOpts(CGO),
104
105
theModule{mlir::ModuleOp::create (builder.getUnknownLoc ())}, Diags(Diags),
105
106
target (astCtx.getTargetInfo()), ABI(createCXXABI(*this )), genTypes{*this },
106
- VTables{*this } {
107
+ VTables{*this }, openMPRuntime( new CIRGenOpenMPRuntime(* this )) {
107
108
108
109
// Initialize CIR signed integer types cache.
109
110
SInt8Ty =
@@ -316,7 +317,18 @@ bool CIRGenModule::MustBeEmitted(const ValueDecl *Global) {
316
317
}
317
318
318
319
bool CIRGenModule::MayBeEmittedEagerly (const ValueDecl *Global) {
319
- assert (!langOpts.OpenMP && " NYI" );
320
+ // In OpenMP 5.0 variables and function may be marked as
321
+ // device_type(host/nohost) and we should not emit them eagerly unless we sure
322
+ // that they must be emitted on the host/device. To be sure we need to have
323
+ // seen a declare target with an explicit mentioning of the function, we know
324
+ // we have if the level of the declare target attribute is -1. Note that we
325
+ // check somewhere else if we should emit this at all.
326
+ if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd ) {
327
+ std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
328
+ OMPDeclareTargetDeclAttr::getActiveAttr (Global);
329
+ if (!ActiveAttr || (*ActiveAttr)->getLevel () != (unsigned )-1 )
330
+ return false ;
331
+ }
320
332
321
333
const auto *FD = dyn_cast<FunctionDecl>(Global);
322
334
if (FD) {
@@ -336,6 +348,15 @@ bool CIRGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
336
348
ASTContext::InlineVariableDefinitionKind::WeakUnknown &&
337
349
" not implemented" );
338
350
351
+ // If OpenMP is enabled and threadprivates must be generated like TLS, delay
352
+ // codegen for global variables, because they may be marked as threadprivate.
353
+ if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
354
+ getASTContext ().getTargetInfo ().isTLSSupported () &&
355
+ isa<VarDecl>(Global) &&
356
+ !Global->getType ().isConstantStorage (getASTContext (), false , false ) &&
357
+ !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration (Global))
358
+ return false ;
359
+
339
360
assert ((FD || VD) &&
340
361
" Only FunctionDecl and VarDecl should hit this path so far." );
341
362
return true ;
@@ -347,7 +368,22 @@ void CIRGenModule::buildGlobal(GlobalDecl GD) {
347
368
assert (!Global->hasAttr <IFuncAttr>() && " NYI" );
348
369
assert (!Global->hasAttr <CPUDispatchAttr>() && " NYI" );
349
370
assert (!langOpts.CUDA && " NYI" );
350
- assert (!langOpts.OpenMP && " NYI" );
371
+
372
+ if (langOpts.OpenMP ) {
373
+ // If this is OpenMP, check if it is legal to emit this global normally.
374
+ if (openMPRuntime && openMPRuntime->emitTargetGlobal (GD)) {
375
+ assert (!UnimplementedFeature::openMPRuntime ());
376
+ return ;
377
+ }
378
+ if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Global)) {
379
+ assert (!UnimplementedFeature::openMP ());
380
+ return ;
381
+ }
382
+ if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Global)) {
383
+ assert (!UnimplementedFeature::openMP ());
384
+ return ;
385
+ }
386
+ }
351
387
352
388
// Ignore declarations, they will be emitted on their first use.
353
389
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
@@ -371,7 +407,13 @@ void CIRGenModule::buildGlobal(GlobalDecl GD) {
371
407
assert (VD->isFileVarDecl () && " Cannot emit local var decl as global." );
372
408
if (VD->isThisDeclarationADefinition () != VarDecl::Definition &&
373
409
!astCtx.isMSStaticDataMemberInlineDefinition (VD)) {
374
- assert (!getLangOpts ().OpenMP && " not implemented" );
410
+ if (langOpts.OpenMP ) {
411
+ // Emit declaration of the must-be-emitted declare target variable.
412
+ if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
413
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration (VD)) {
414
+ assert (0 && " OMPDeclareTargetDeclAttr NYI" );
415
+ }
416
+ }
375
417
// If this declaration may have caused an inline variable definition
376
418
// to change linkage, make sure that it's emitted.
377
419
// TODO(cir): probably use GetAddrOfGlobalVar(VD) below?
@@ -576,8 +618,8 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef MangledName, mlir::Type Ty,
576
618
!D->hasAttr <clang::DLLExportAttr>())
577
619
assert (!UnimplementedFeature::setDLLStorageClass () && " NYI" );
578
620
579
- if (getLangOpts () .OpenMP && !getLangOpts () .OpenMPSimd && D)
580
- assert ( 0 && " not implemented " );
621
+ if (langOpts .OpenMP && !langOpts .OpenMPSimd && D)
622
+ getOpenMPRuntime (). registerTargetGlobalVariable (D, Entry );
581
623
582
624
// TODO(cir): check TargetAS matches Entry address space
583
625
if (Entry.getSymType () == Ty &&
@@ -647,10 +689,9 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef MangledName, mlir::Type Ty,
647
689
}
648
690
649
691
// Handle things which are present even on external declarations.
650
- auto &LangOpts = getLangOpts ();
651
692
if (D) {
652
- if (LangOpts .OpenMP && !LangOpts .OpenMPSimd )
653
- assert ( 0 && " not implemented " );
693
+ if (langOpts .OpenMP && !langOpts .OpenMPSimd && D )
694
+ getOpenMPRuntime (). registerTargetGlobalVariable (D, Entry );
654
695
655
696
// FIXME: This code is overly simple and should be merged with other global
656
697
// handling.
@@ -2052,8 +2093,11 @@ mlir::cir::FuncOp CIRGenModule::GetOrCreateCIRFunction(
2052
2093
// Any attempts to use a MultiVersion function should result in retrieving the
2053
2094
// iFunc instead. Name mangling will handle the rest of the changes.
2054
2095
if (const auto *FD = cast_or_null<FunctionDecl>(D)) {
2055
- if (getLangOpts ().OpenMP )
2056
- llvm_unreachable (" open MP NYI" );
2096
+ // For the device mark the function as one that should be emitted.
2097
+ if (getLangOpts ().OpenMPIsTargetDevice && FD->isDefined () && !DontDefer &&
2098
+ !IsForDefinition) {
2099
+ assert (0 && " OpenMP target functions NYI" );
2100
+ }
2057
2101
if (FD->isMultiVersion ())
2058
2102
llvm_unreachable (" NYI" );
2059
2103
}
@@ -2291,9 +2335,9 @@ void CIRGenModule::buildGlobalDecl(clang::GlobalDecl &D) {
2291
2335
}
2292
2336
2293
2337
// If this is OpenMP, check if it is legal to emit this global normally.
2294
- if (getLangOpts ().OpenMP ) {
2295
- llvm_unreachable ( " NYI " );
2296
- }
2338
+ if (getLangOpts ().OpenMP && openMPRuntime &&
2339
+ openMPRuntime-> emitTargetGlobal (D))
2340
+ return ;
2297
2341
2298
2342
// Otherwise, emit the definition and move on to the next one.
2299
2343
buildGlobalDefinition (D, Op);
@@ -2302,7 +2346,7 @@ void CIRGenModule::buildGlobalDecl(clang::GlobalDecl &D) {
2302
2346
void CIRGenModule::buildDeferred (unsigned recursionLimit) {
2303
2347
// Emit deferred declare target declarations
2304
2348
if (getLangOpts ().OpenMP && !getLangOpts ().OpenMPSimd )
2305
- llvm_unreachable ( " NYI " );
2349
+ getOpenMPRuntime (). emitDeferredTargetDecls ( );
2306
2350
2307
2351
// Emit code for any potentially referenced deferred decls. Since a previously
2308
2352
// unused static decl may become used during the generation of code for a
0 commit comments