Author: Erich Keane Date: 2026-08-13T13:07:24-07:00 New Revision: 02da5ba79cb0bf1d95634ffe060802ff2d4a0292
URL: https://github.com/llvm/llvm-project/commit/02da5ba79cb0bf1d95634ffe060802ff2d4a0292 DIFF: https://github.com/llvm/llvm-project/commit/02da5ba79cb0bf1d95634ffe060802ff2d4a0292.diff LOG: [CIR] Implement the 'rest' of the TLS Model types (#215380) Functionally, the only difference between these models is the tag that goes onto the variable in the LLVM-IR. This patch changes our "== GeneralDynamic" checks to just be whether they have a TLS Model defined, so all the previous logic still holds. This patch DOES have to add the 'default' model to the module, as the top-level TLS guard needs to have this model, even if the individual variables are overridden by the tls_model attribute. Like the previous inline-printing patch, this ensures we print the module result attribute as an enum value instead an integral. This requires some custom parse/printing here, but is pretty routine. We can't convert GlobalOp without vastly changing how it prints these, as there isn't really a 'assemblyFormat' that works for this printed as an 'attribute' and a keyword. We ALSO had to change the name of the enum to be TLSModel, because MLIR is inconsistent in tablegen where it gets the name from on an enum, so it would pick up the wrong spelling sometimes. Added: clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp clang/test/CIR/CodeGen/tls-model-func-scope.cpp Modified: clang/include/clang/CIR/Dialect/IR/CIRDialect.td clang/include/clang/CIR/Dialect/IR/CIROps.td clang/lib/CIR/CodeGen/CIRGenDeclCXX.cpp clang/lib/CIR/CodeGen/CIRGenModule.cpp clang/lib/CIR/CodeGen/CIRGenModule.h clang/lib/CIR/Dialect/IR/CIRDialect.cpp clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp clang/test/CIR/CodeGen/global-ctor-dtor.cpp clang/test/CIR/CodeGen/global-temp-dtor.cpp clang/test/CIR/CodeGen/global-tls-dyn-init.cpp clang/test/CIR/CodeGen/global-tls-simple-init.cpp clang/test/CIR/CodeGen/global-tls-templates.cpp clang/test/CIR/CodeGen/thread-local-in-func.cpp clang/test/CIR/CodeGen/tls-model.cpp clang/test/CIR/CodeGen/tls.c clang/test/CIR/IR/global.cir clang/test/CIR/IR/invalid-tls.cir Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index 8829d37a52c97..d974cb1fa4544 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -89,6 +89,7 @@ def CIR_Dialect : Dialect { static llvm::StringRef getAMDGPUXnackAttrName() { return "cir.amdgpu_xnack"; } static llvm::StringRef getAMDGPUSramEccAttrName() { return "cir.amdgpu_sramecc"; } static llvm::StringRef getOpenCLKernelArgMetadataAttrName() { return "cir.cl.kernel_arg_metadata"; } + static llvm::StringRef getDefaultTlsModelAttrName() { return "cir.default_tls_model"; } void registerAttributes(); void registerTypes(); diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index e63e98033eb9a..97ce54840ff38 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3301,12 +3301,22 @@ def CIR_GlobalLinkageKind : CIR_I32EnumAttr< // properties of a global variable will be added over time as more of ClangIR // is upstreamed. -def CIR_TLSModel : CIR_I32EnumAttr<"TLS_Model", "TLS model", [ +def CIR_TLSModel : CIR_I32EnumAttr<"TLSModel", "TLS model", [ I32EnumAttrCase<"GeneralDynamic", 1, "tls_dyn">, I32EnumAttrCase<"LocalDynamic", 2, "tls_local_dyn">, I32EnumAttrCase<"InitialExec", 3, "tls_init_exec">, I32EnumAttrCase<"LocalExec", 4, "tls_local_exec"> -]>; + ]> { + let genSpecializedAttr = 0; +} + +def CIR_TLSModelAttr: CIR_EnumAttr<CIR_TLSModel, "tls_model"> { + let summary = "TLS Model attribute"; + let description = [{ + The TLS mode for the global, which comes from either the + `tls_model` attribute, or `-ftls-model` flag. + }]; +} def CIR_GlobalOp : CIR_Op<"global", [ DeclareOpInterfaceMethods<RegionBranchOpInterface, ["getSuccessorInputs"]>, @@ -3347,8 +3357,8 @@ def CIR_GlobalOp : CIR_Op<"global", [ TypeAttr:$sym_type, CIR_GlobalLinkageKind:$linkage, OptionalAttr<MemorySpaceAttrInterface>:$addr_space, - OptionalAttr<CIR_TLSModel>:$tls_model, - OptionalAttr<CIR_ThreadLocalGlobalWrapperInitAttr>:$dyn_tls_refs, + OptionalAttr<CIR_TLSModelAttr>:$tls_model, + OptionalAttr<CIR_ThreadLocalGlobalWrapperInitAttr>:$tls_refs, OptionalAttr<AnyAttr>:$initial_value, UnitProp:$comdat, UnitProp:$constant, @@ -3371,8 +3381,8 @@ def CIR_GlobalOp : CIR_Op<"global", [ (`constant` $constant^)? $linkage (`comdat` $comdat^)? - ($tls_model^)? - (`dyn_tls_refs` `=` $dyn_tls_refs^)? + (`tls_model` `=` $tls_model^)? + (`tls_refs` `=` $tls_refs^)? (`dso_local` $dso_local^)? (`static_local_guard` `` $static_local_guard^)? (` ` custom<GlobalAddressSpaceValue>($addr_space)^ )? diff --git a/clang/lib/CIR/CodeGen/CIRGenDeclCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenDeclCXX.cpp index 03929e50f44f9..2bcef48739dfa 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDeclCXX.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDeclCXX.cpp @@ -68,7 +68,8 @@ void CIRGenModule::setGlobalTlsReferences(const VarDecl &vd, if (!getLangOpts().CPlusPlus) return; - if (globalOp.getTlsModel() != cir::TLS_Model::GeneralDynamic) + // TLS Static doesn't need a wrapper. + if (vd.getTLSKind() != VarDecl::TLS_Dynamic) return; llvm::SmallString<256> wrapperFuncName; @@ -94,7 +95,7 @@ void CIRGenModule::setGlobalTlsReferences(const VarDecl &vd, "setGlobalTlsReferences: non-itanium mangler"); return; } - globalOp.setDynTlsRefsAttr(cir::ThreadLocalGlobalWrapperInitAttr::get( + globalOp.setTlsRefsAttr(cir::ThreadLocalGlobalWrapperInitAttr::get( &getMLIRContext(), wrapperFuncName, initFuncName, guardName)); } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 9ddd65e80f800..50ee0cfe48d26 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -144,6 +144,10 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, cgo.OptimizationLevel, cgo.OptimizeSize)); + theModule->setAttr( + cir::CIRDialect::getDefaultTlsModelAttrName(), + cir::TLSModelAttr::get(&mlirContext, getDefaultCIRTLSModel())); + if (langOpts.OpenMP) { mlir::omp::OffloadModuleOpts ompOpts( langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription, @@ -3095,24 +3099,24 @@ bool CIRGenModule::lookupRepresentativeDecl(StringRef mangledName, return true; } -static cir::TLS_Model getCIRTLSModel(StringRef S) { - return llvm::StringSwitch<cir::TLS_Model>(S) - .Case("global-dynamic", cir::TLS_Model::GeneralDynamic) - .Case("local-dynamic", cir::TLS_Model::LocalDynamic) - .Case("initial-exec", cir::TLS_Model::InitialExec) - .Case("local-exec", cir::TLS_Model::LocalExec); +static cir::TLSModel getCIRTLSModel(StringRef S) { + return llvm::StringSwitch<cir::TLSModel>(S) + .Case("global-dynamic", cir::TLSModel::GeneralDynamic) + .Case("local-dynamic", cir::TLSModel::LocalDynamic) + .Case("initial-exec", cir::TLSModel::InitialExec) + .Case("local-exec", cir::TLSModel::LocalExec); } -cir::TLS_Model CIRGenModule::getDefaultCIRTLSModel() const { +cir::TLSModel CIRGenModule::getDefaultCIRTLSModel() const { switch (getCodeGenOpts().getDefaultTLSModel()) { case CodeGenOptions::GeneralDynamicTLSModel: - return cir::TLS_Model::GeneralDynamic; + return cir::TLSModel::GeneralDynamic; case CodeGenOptions::LocalDynamicTLSModel: - return cir::TLS_Model::LocalDynamic; + return cir::TLSModel::LocalDynamic; case CodeGenOptions::InitialExecTLSModel: - return cir::TLS_Model::InitialExec; + return cir::TLSModel::InitialExec; case CodeGenOptions::LocalExecTLSModel: - return cir::TLS_Model::LocalExec; + return cir::TLSModel::LocalExec; } llvm_unreachable("Invalid TLS model!"); } @@ -3121,7 +3125,7 @@ void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d, bool isExtendingDecl) { assert(d.getTLSKind() && "setting TLS mode on non-TLS var!"); - cir::TLS_Model tlm = getDefaultCIRTLSModel(); + cir::TLSModel tlm = getDefaultCIRTLSModel(); // Override the TLS model if it is explicitly specified. if (const auto *attr = d.getAttr<TLSModelAttr>()) @@ -3132,7 +3136,7 @@ void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d, // For namespace-scope dyanmic TLS we need to set the wrapper, int, or guard // info. - if (d.isStaticLocal() || tlm != cir::TLS_Model::GeneralDynamic) + if (d.isStaticLocal()) return; // If this function was called to set the TLS mode for a temporary whose diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index ba7b20b91cc03..9d19a58a05b4d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -637,7 +637,7 @@ class CIRGenModule : public CIRGenTypeCache { bool isExtendingDecl = false); /// Get TLS mode from CodeGenOptions. - cir::TLS_Model getDefaultCIRTLSModel() const; + cir::TLSModel getDefaultCIRTLSModel() const; /// Set function attributes for a function declaration. void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f, diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 655fe6bfe5858..a759e087afdc8 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2104,12 +2104,11 @@ mlir::LogicalResult cir::GlobalOp::verify() { "Cannot have a static-local global-op with a constructor or " "destructor, they require in-function initialization via LocalInitOp"); - if (getDynTlsRefs()) { + if (getTlsRefs()) { if (getStaticLocalGuard().has_value()) - return emitOpError( - "cannot have both static local and dynamic tls references"); - if (!getTlsModel() || getTlsModel() != TLS_Model::GeneralDynamic) - return emitOpError("'dyn_tls_refs' only valid for dynamic tls"); + return emitOpError("cannot have both static local and tls references"); + if (!getTlsModel()) + return emitOpError("'tls_refs' only valid for tls"); } if (getAliasee().has_value()) { diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 815df47f82231..28ba14962cc7b 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -1193,13 +1193,13 @@ LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(cir::GlobalOp op) { // If this is a global TLS variable (that is, declared at namespace scope), we // have to emit the guard variable here. - bool needsTlsGuard = op.getDynTlsRefs() && op.getDynTlsRefs()->getGuardName(); + bool needsTlsGuard = op.getTlsRefs() && op.getTlsRefs()->getGuardName(); cir::IfOp guardIf; if (needsTlsGuard) { guardIf = buildGlobalTlsGuardCheck( builder, op.getLoc(), getOrCreateStaticLocalDeclGuardAddress( - builder, op, op.getDynTlsRefs()->getGuardName().getValue(), + builder, op, op.getTlsRefs()->getGuardName().getValue(), /*isLocalVarDecl=*/false, /*useInt8GuardVariable=*/op.hasInternalLinkage())); builder.setInsertionPointToEnd(&guardIf.getThenRegion().front()); @@ -1460,10 +1460,12 @@ void LoweringPreparePass::lowerLocalInitOp(cir::LocalInitOp initOp) { // Remove the init local op, now that we've done everything we need with it. initOp.erase(); } -static bool isThreadWrapperReplaceable(cir::TLS_Model tls, - clang::ASTContext &astCtx) { - return tls == cir::TLS_Model::GeneralDynamic && - astCtx.getTargetInfo().getTriple().isOSDarwin(); +static bool isThreadWrapperReplaceable(clang::ASTContext &astCtx) { + // Note: Classic codegen needs to check that the VarDecl.getTLSKind() == + // TLS_Dynamic, but we don't attempt to emit the thread wrapper unless that is + // already the case. So the only thing that matters here is whether it is + // darwin. + return astCtx.getTargetInfo().getTriple().isOSDarwin(); } static cir::GlobalLinkageKind @@ -1471,7 +1473,7 @@ getThreadLocalWrapperLinkage(GlobalOp op, clang::ASTContext &astCtx) { if (isLocalLinkage(op.getLinkage())) return op.getLinkage(); - if (isThreadWrapperReplaceable(*op.getTlsModel(), astCtx)) + if (isThreadWrapperReplaceable(astCtx)) if (!isLinkOnceLinkage(op.getLinkage()) && !isWeakODRLinkage(op.getLinkage())) return op.getLinkage(); @@ -1489,7 +1491,7 @@ LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder, mlir::OpBuilder::InsertionGuard insertGuard(builder); builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front()); - mlir::StringAttr wrapperName = op.getDynTlsRefs()->getWrapperName(); + mlir::StringAttr wrapperName = op.getTlsRefs()->getWrapperName(); auto existingWrapperIter = threadLocalWrappers.find(wrapperName.getValue()); if (existingWrapperIter != threadLocalWrappers.end()) @@ -1515,12 +1517,12 @@ LoweringPreparePass::getOrCreateThreadLocalWrapper(CIRBaseBuilderTy &builder, func, mlir::SymbolTable::Visibility::Private); if (!isLocalLinkage(linkageKind)) { - if (!isThreadWrapperReplaceable(*op.getTlsModel(), *astCtx) || + if (!isThreadWrapperReplaceable(*astCtx) || isLinkOnceLinkage(linkageKind) || isWeakODRLinkage(linkageKind) || op.getGlobalVisibility() == cir::VisibilityKind::Hidden) func.setGlobalVisibility(cir::VisibilityKind::Hidden); } - if (isThreadWrapperReplaceable(*op.getTlsModel(), *astCtx)) + if (isThreadWrapperReplaceable(*astCtx)) op->emitError("Unhandled thread wrapper attributes for CC and Nounwind"); threadLocalWrappers.insert({wrapperName.getValue(), func}); @@ -1568,7 +1570,7 @@ LoweringPreparePass::defineGlobalThreadLocalInitAlias(cir::GlobalOp op, CIRBaseBuilderTy builder(getContext()); mlir::OpBuilder::InsertionGuard insertGuard(builder); builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front()); - mlir::StringAttr aliasName = op.getDynTlsRefs()->getInitName(); + mlir::StringAttr aliasName = op.getTlsRefs()->getInitName(); auto existingAliasIter = threadLocalInitAliases.find(aliasName.getValue()); if (existingAliasIter != threadLocalInitAliases.end()) @@ -1613,8 +1615,7 @@ void LoweringPreparePass::lowerGlobalOp(GlobalOp op) { dtorRegion.getBlocks().clear(); assert(!cir::MissingFeatures::astVarDeclInterface()); - if (op.getTlsModel() == TLS_Model::GeneralDynamic && - !op.getStaticLocalGuard().has_value()) { + if (op.getTlsModel() && !op.getStaticLocalGuard().has_value()) { // There are two types of global TLS variables: 'ordered' and 'unordered'. // 'ordered' are the common case. A call to any of them causes all of the // initializers for all other 'ordered' ones to be called, via a @@ -1626,7 +1627,7 @@ void LoweringPreparePass::lowerGlobalOp(GlobalOp op) { // a guard variable for them (since they cannot use the global guard), so // we diff erentiate them that way. - if (op.getDynTlsRefs()->getGuardName()) { + if (op.getTlsRefs()->getGuardName()) { // Unordered: the alias is the function we just generated. initAlias = defineGlobalThreadLocalInitAlias(op, f); } else { @@ -1640,17 +1641,16 @@ void LoweringPreparePass::lowerGlobalOp(GlobalOp op) { } else { dynamicInitializers.push_back(f); } - } else if (op.getTlsModel() == TLS_Model::GeneralDynamic && - op.getDynTlsRefs() && op.isDeclaration()) { + } else if (op.getTlsModel() && op.getTlsRefs() && op.isDeclaration()) { // If this is a declaration and has no init function, we probably DO have to // create an alias that needs checking, so create it as extern-weak. initAlias = defineGlobalThreadLocalInitAlias(op, {}); } // We need a wrapper for TLS globals that MIGHT have a non-constant - // initialization. The FE will have generated the DynTlsRefs for any with + // initialization. The FE will have generated the TlsRefs for any with // known dynamic init, or unknown (extern) init. - if (op.getTlsModel() == TLS_Model::GeneralDynamic && op.getDynTlsRefs()) + if (op.getTlsModel() && op.getTlsRefs()) defineGlobalThreadLocalWrapper(op, initAlias, !op.isDeclaration()); assert(!cir::MissingFeatures::opGlobalAnnotations()); @@ -1666,8 +1666,7 @@ void LoweringPreparePass::lowerGetGlobalOp(GetGlobalOp op) { // get-global operations rewritten to be calls to a wrapper function. If // we're not in a dynamic TLS (or one without the TLS markers), we can leave // this one as a get-global and return early. - if (globalOp.getTlsModel() != TLS_Model::GeneralDynamic || - !globalOp.getDynTlsRefs()) + if (!globalOp.getTlsModel() || !globalOp.getTlsRefs()) return; // If this is a global TLS, we need to replace the call to 'get_global' with a @@ -1792,9 +1791,15 @@ LoweringPreparePass::createGlobalThreadLocalGuard(CIRBaseBuilderTy &builder, g.setLinkageAttr(cir::GlobalLinkageKindAttr::get( builder.getContext(), cir::GlobalLinkageKind::InternalLinkage)); g.setAlignment(clang::CharUnits::One().getAsAlign().value()); - // At the moment, we only have implementation for this mode, as it is the - // default. At one point we might need to load this mode from the module. - g.setTlsModel(TLS_Model::GeneralDynamic); + + if (auto defTlsModel = mlirModule->getAttrOfType<TLSModelAttr>( + cir::CIRDialect::getDefaultTlsModelAttrName())) { + g.setTlsModel(defTlsModel.getValue()); + } else { + // Default value, unless overridden in the IR/by the frontend. + g.setTlsModel(TLSModel::GeneralDynamic); + } + g.setInitialValueAttr(cir::IntAttr::get(guardTy, 0)); return g; } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index ccdc974ca1b93..99e1643c4d9c4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2805,10 +2805,10 @@ CIRToLLVMGlobalOpLowering::lowerGlobalAttributes( } static mlir::LLVM::ThreadLocalMode -convertTlsModelAttrToLLVM(TLS_ModelAttr attr) { +convertTlsModelAttrToLLVM(TLSModelAttr attr) { // assert that we can just static-cast these. #define CHECK_ENUM(CIR, LLVM_VAL) \ - static_assert(static_cast<unsigned>(TLS_Model::CIR) == \ + static_assert(static_cast<unsigned>(TLSModel::CIR) == \ static_cast<unsigned>(mlir::LLVM::ThreadLocalMode::LLVM_VAL)) CHECK_ENUM(GeneralDynamic, GeneralDynamic); CHECK_ENUM(LocalDynamic, LocalDynamic); diff --git a/clang/test/CIR/CodeGen/global-ctor-dtor.cpp b/clang/test/CIR/CodeGen/global-ctor-dtor.cpp index 63f175281a02e..e58261ebf5446 100644 --- a/clang/test/CIR/CodeGen/global-ctor-dtor.cpp +++ b/clang/test/CIR/CodeGen/global-ctor-dtor.cpp @@ -36,7 +36,7 @@ void foo4(void) { // CIR-BEFORE-LPP: cir.func {{.*}} @_Z4foo4v() global_dtor(789) -// CIR-AFTER: module @{{.*}} attributes {cir.global_ctors = [#cir.global_ctor<"_Z3foov", 65535>, #cir.global_ctor<"_Z4foo2v", 777>], cir.global_dtors = [#cir.global_dtor<"_Z4foo3v", 65535>, #cir.global_dtor<"_Z4foo4v", 789>] +// CIR-AFTER: module @{{.*}} attributes {{{.*}}cir.global_ctors = [#cir.global_ctor<"_Z3foov", 65535>, #cir.global_ctor<"_Z4foo2v", 777>], cir.global_dtors = [#cir.global_dtor<"_Z4foo3v", 65535>, #cir.global_dtor<"_Z4foo4v", 789>] // LLVM: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_Z3foov, ptr null }, { i32, ptr, ptr } { i32 777, ptr @_Z4foo2v, ptr null }] // LLVM: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_Z4foo3v, ptr null }, { i32, ptr, ptr } { i32 789, ptr @_Z4foo4v, ptr null }] diff --git a/clang/test/CIR/CodeGen/global-temp-dtor.cpp b/clang/test/CIR/CodeGen/global-temp-dtor.cpp index a59f7d8e72c40..31da2ee080360 100644 --- a/clang/test/CIR/CodeGen/global-temp-dtor.cpp +++ b/clang/test/CIR/CodeGen/global-temp-dtor.cpp @@ -47,7 +47,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{}; // CIR: cir.call @__cxa_atexit // CIR: cir.global "private" internal @_ZGR10static_ref_ = #cir.zero : !rec_NonTrivial -// CIR-BEFORE: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = ctor : !cir.ptr<!rec_NonTrivial> { +// CIR-BEFORE: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = ctor : !cir.ptr<!rec_NonTrivial> { // CIR-BEFORE: %[[THREAD_REF:.*]] = cir.get_global thread_local @thread_ref // CIR-BEFORE: %[[REF_TEMP:.*]] = cir.get_global @_ZGR10thread_ref_ // CIR-BEFORE: cir.call @_ZN10NonTrivialC1Ev(%[[REF_TEMP]]) @@ -56,9 +56,9 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{}; // CIR-BEFORE: %[[REF_TEMP_DTOR:.*]] = cir.get_global @_ZGR10thread_ref_ // CIR-BEFORE: cir.call @_ZN10NonTrivialD1Ev(%[[REF_TEMP_DTOR]]) // CIR-BEFORE: } -// CIR-BEFORE: cir.global "private" internal tls_dyn @_ZGR10thread_ref_ = #cir.zero : !rec_NonTrivial +// CIR-BEFORE: cir.global "private" internal tls_model = <tls_dyn> @_ZGR10thread_ref_ = #cir.zero : !rec_NonTrivial -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = #cir.ptr<null> : !cir.ptr<!rec_NonTrivial> +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = #cir.ptr<null> : !cir.ptr<!rec_NonTrivial> // CIR: cir.func internal private @__cxx_global_var_init.1() // CIR: cir.get_global thread_local @thread_ref // CIR: cir.get_global @_ZGR10thread_ref_ @@ -68,7 +68,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{}; // CIR: cir.get_global @_ZN10NonTrivialD1Ev // CIR: cir.get_global @__dso_handle // CIR: cir.call @__cxa_thread_atexit -// CIR: cir.global "private" internal tls_dyn @_ZGR10thread_ref_ = #cir.zero : !rec_NonTrivial +// CIR: cir.global "private" internal tls_model = <tls_dyn> @_ZGR10thread_ref_ = #cir.zero : !rec_NonTrivial // CIR-BEFORE: cir.global external @static_arr_ref = ctor : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> { // CIR-BEFORE: %[[ARRAY_INIT_TEMP:.*]] = cir.alloca {{.*}}"arrayinit.temp" @@ -108,7 +108,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{}; // CIR: cir.call @__cxa_atexit // CIR: cir.global "private" internal @_ZGR14static_arr_ref_ = #cir.zero : !cir.array<!rec_NonTrivial x 2> -// CIR-BEFORE: cir.global external tls_dyn dyn_tls_refs = <"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = ctor : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> { +// CIR-BEFORE: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = ctor : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> { // CIR-BEFORE: %[[ARRAY_INIT_TEMP:.*]] = cir.alloca {{.*}}"arrayinit.temp" // CIR-BEFORE: %[[THREAD_ARR_REF:.*]] = cir.get_global thread_local @thread_arr_ref // CIR-BEFORE: %[[THREAD_ARR_REF_TEMP:.*]] = cir.get_global @_ZGR14thread_arr_ref_ @@ -129,9 +129,9 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{}; // CIR-BEFORE: cir.call @_ZN10NonTrivialD1Ev(%[[ELEMENT]]) // CIR-BEFORE: } // CIR-BEFORE: } -// CIR-BEFORE: cir.global "private" internal tls_dyn @_ZGR14thread_arr_ref_ = #cir.zero : !cir.array<!rec_NonTrivial x 2> +// CIR-BEFORE: cir.global "private" internal tls_model = <tls_dyn> @_ZGR14thread_arr_ref_ = #cir.zero : !cir.array<!rec_NonTrivial x 2> -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = #cir.ptr<null> : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = #cir.ptr<null> : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> // CIR: cir.func internal private @__cxx_global_array_dtor.1( // CIR: cir.do { // CIR: cir.call @_ZN10NonTrivialD1Ev @@ -144,7 +144,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{}; // CIR: cir.get_global @__cxx_global_array_dtor.1 // CIR: cir.get_global @__dso_handle // CIR: cir.call @__cxa_thread_atexit -// CIR: cir.global "private" internal tls_dyn @_ZGR14thread_arr_ref_ = #cir.zero : !cir.array<!rec_NonTrivial x 2> +// CIR: cir.global "private" internal tls_model = <tls_dyn> @_ZGR14thread_arr_ref_ = #cir.zero : !cir.array<!rec_NonTrivial x 2> // LLVM-DAG: @static_ref = global ptr null // LLVM-DAG: @_ZGR10static_ref_ = internal global %struct.NonTrivial zeroinitializer diff --git a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp index 68973223eb303..5391afcbdfb34 100644 --- a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp +++ b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp @@ -23,7 +23,7 @@ struct CtorDtor { // LLVM-BOTH-DAG: @_ZTH6tls_cd = alias void (), ptr @__tls_init // Wrappers & aliases. -// CIR: cir.global internal tls_dyn @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} +// CIR: cir.global internal tls_model = <tls_dyn> @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} // CIR-LABEL: cir.func comdat weak_odr private hidden @_ZTW19tls_cd_dyn_not_used() -> !cir.ptr<!rec_CtorDtor> { // CIR: cir.call @_ZTH19tls_cd_dyn_not_used() : () -> () // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> @@ -100,11 +100,11 @@ struct CtorDtor { // LLVM: call void @[[TLS_CD_DYN_NOT_USED_INIT:.*]]() thread_local CtorDtor tls_cd = 5; -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW6tls_cd", "_ZTH6tls_cd"> @tls_cd = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_CtorDtor dtor { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW6tls_cd", "_ZTH6tls_cd"> @tls_cd = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_CtorDtor dtor { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorD1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_CtorDtor>) -> () // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW6tls_cd", "_ZTH6tls_cd"> @tls_cd = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_CtorDtor +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW6tls_cd", "_ZTH6tls_cd"> @tls_cd = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_CtorDtor // CIR: cir.func internal private @[[TLS_CD_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd : !cir.ptr<!rec_CtorDtor> // CIR: %[[GET_DTOR:.*]] = cir.get_global @_ZN8CtorDtorD1Ev : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> @@ -122,7 +122,7 @@ thread_local CtorDtor tls_cd = 5; // LLVM-BOTH: ret void thread_local CtorDtor tls_cd_dyn = get_i(); -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = ctor : !rec_CtorDtor { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = ctor : !rec_CtorDtor { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : (!cir.ptr<!rec_CtorDtor> @@ -130,7 +130,7 @@ thread_local CtorDtor tls_cd_dyn = get_i(); // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorD1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_CtorDtor>) -> () // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = #cir.zero : !rec_CtorDtor +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = #cir.zero : !rec_CtorDtor // CIR: cir.func internal private @[[TLS_CD_DYN_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> // CIR: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) @@ -155,12 +155,12 @@ thread_local CtorDtor tls_cd_dyn = get_i(); // LLVM-BOTH: ret void thread_local CtorDtor &tls_cd_ref = tls_cd_dyn; -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = ctor : !cir.ptr<!rec_CtorDtor> { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = ctor : !cir.ptr<!rec_CtorDtor> { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor>, !cir.ptr<!cir.ptr<!rec_CtorDtor>> // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = #cir.ptr<null> : !cir.ptr<!rec_CtorDtor> +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = #cir.ptr<null> : !cir.ptr<!rec_CtorDtor> // CIR: cir.func internal private @[[TLS_CD_REF_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>> // CIR: %[[GET_DYN:.*]] = cir.call @_ZTW10tls_cd_dyn() : () -> !cir.ptr<!rec_CtorDtor> @@ -182,7 +182,7 @@ thread_local CtorDtor &tls_cd_ref = tls_cd_dyn; // OGCG: } thread_local CtorDtor tls_cd_dyn_not_used = get_i(); -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = ctor : !rec_CtorDtor { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = ctor : !rec_CtorDtor { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) @@ -190,7 +190,7 @@ thread_local CtorDtor tls_cd_dyn_not_used = get_i(); // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorD1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_CtorDtor>) -> () // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = #cir.zero : !rec_CtorDtor +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = #cir.zero : !rec_CtorDtor // CIR: cir.func internal private @[[TLS_CD_DYN_NOT_USED_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> // CIR: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) diff --git a/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp b/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp new file mode 100644 index 0000000000000..88881f7cb3119 --- /dev/null +++ b/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s --check-prefix=CIR-BEFORE-LPP +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR,NOWRAP +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM,NOWRAP +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM,NOWRAP + +int f(); +__thread int a = 5; +_Thread_local int b = 5; +thread_local int c = 5; +thread_local int d = f(); + +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> @a = #cir.int<5> : !s32i +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> @b = #cir.int<5> : !s32i +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW1c", "_ZTH1c"> @c = #cir.int<5> : !s32i +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW1d", "_ZTH1d"> @d = ctor + +// CIR-DAG: cir.global external tls_model = <tls_dyn> @a = #cir.int<5> : !s32i +// CIR-DAG: cir.global external tls_model = <tls_dyn> @b = #cir.int<5> : !s32i + +// CIR-DAG: cir.global internal tls_model = <tls_dyn> @__tls_guard = #cir.int<0> : !s8i +// CIR-DAG: cir.func internal private @__tls_init() +// CIR-DAG: cir.func internal private @__cxx_global_var_init() + +// CIR-DAG: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW1c", "_ZTH1c"> @c = #cir.int<5> : !s32i +// CIR-DAG: cir.func comdat weak_odr private hidden @_ZTW1c() +// Note: C doesn't get an alias since it doesn't have an init function. + +// CIR-DAG: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW1d", "_ZTH1d"> @d = #cir.int<0> : !s32i +// CIR-DAG: cir.func comdat weak_odr private hidden @_ZTW1d() -> !cir.ptr<!s32i> +// CIR-DAG: cir.func @_ZTH1d() alias(@__tls_init) + +// LLVM-DAG: @__tls_guard = internal thread_local global i8 0 +// LLVM-DAG: define internal void @__tls_init() +// LLVM-DAG: define internal void @__cxx_global_var_init() + +// LLVM-DAG: @a = thread_local global i32 5 +// LLVM-DAG: @b = thread_local global i32 5 +// LLVM-DAG: @c = thread_local global i32 5 +// LLVM-DAG: define weak_odr hidden {{.*}}ptr @_ZTW1c() + +// LLVM-DAG: @d = thread_local global i32 0 +// LLVM-DAG: @_ZTH1d = alias void (), ptr @__tls_init +// LLVM-DAG: define weak_odr hidden {{.*}}ptr @_ZTW1d() + +// NOWRAP-NOT: @_ZTW1a +// NOWRAP-NOT: @_ZTH1a +// NOWRAP-NOT: @_ZTW1b +// NOWRAP-NOT: @_ZTH1b +// NOWRAP-NOT: @_ZTH1c diff --git a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp index 4d480bfa64f5b..23698ceda845c 100644 --- a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp +++ b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp @@ -140,16 +140,16 @@ struct CtorDtor { thread_local int tls_int = 5; -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW7tls_int", "_ZTH7tls_int"> @tls_int = #cir.int<5> : !s32i -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW7tls_int", "_ZTH7tls_int"> @tls_int = #cir.int<5> : !s32i +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW7tls_int", "_ZTH7tls_int"> @tls_int = #cir.int<5> : !s32i +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW7tls_int", "_ZTH7tls_int"> @tls_int = #cir.int<5> : !s32i thread_local int tls_int_dyn = get_i(); -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = ctor : !s32i { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = ctor : !s32i { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_dyn : !cir.ptr<!s32i> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) // CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i> // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = #cir.int<0> : !s32i +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = #cir.int<0> : !s32i // CIR: cir.func internal private @[[TLS_INT_DYN_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_dyn : !cir.ptr<!s32i> // CIR: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) @@ -164,12 +164,12 @@ thread_local int tls_int_dyn = get_i(); // LLVM-BOTH: ret void thread_local int &tls_int_ref = tls_int_dyn; -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = ctor : !cir.ptr<!s32i> { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = ctor : !cir.ptr<!s32i> { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_ref : !cir.ptr<!cir.ptr<!s32i>> // CIR-BEFORE-LPP: %[[GET_OTHER:.*]] = cir.get_global thread_local @tls_int_dyn : !cir.ptr<!s32i> // CIR-BEFORE-LPP: cir.store {{.*}}%[[GET_OTHER]], %[[GET_GLOB]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = #cir.ptr<null> : !cir.ptr<!s32i> +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = #cir.ptr<null> : !cir.ptr<!s32i> // CIR: cir.func internal private @[[TLS_INT_REF_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_ref : !cir.ptr<!cir.ptr<!s32i>> // CIR: %[[GET_REF:.*]] = cir.call @_ZTW11tls_int_dyn() : () -> !cir.ptr<!s32i> @@ -189,7 +189,7 @@ thread_local int &tls_int_ref = tls_int_dyn; // OGCG: ret ptr %[[GET_GLOB]] thread_local int tls_int_self_init = tls_int_self_init + get_i(); -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = ctor : !s32i { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = ctor : !s32i { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_self_init : !cir.ptr<!s32i> // CIR-BEFORE-LPP: %[[GET_SELF:.*]] = cir.get_global thread_local @tls_int_self_init : !cir.ptr<!s32i> // CIR-BEFORE-LPP: %[[LOAD_SELF:.*]] = cir.load {{.*}}%[[GET_SELF]] : !cir.ptr<!s32i>, !s32i @@ -197,7 +197,7 @@ thread_local int tls_int_self_init = tls_int_self_init + get_i(); // CIR-BEFORE-LPP: %[[ADD:.*]] = cir.add nsw %[[LOAD_SELF]], %[[CALL]] : !s32i // CIR-BEFORE-LPP: cir.store {{.*}}%[[ADD]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i> // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = #cir.int<0> : !s32i +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = #cir.int<0> : !s32i // CIR: cir.func internal private @[[TLS_INT_SELF_REF_INIT]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_self_init : !cir.ptr<!s32i> // CIR: %[[GET_SELF_FROM_WRAPPER:.*]] = cir.call @_ZTW17tls_int_self_init() : () -> !cir.ptr<!s32i> @@ -223,16 +223,16 @@ thread_local int tls_int_self_init = tls_int_self_init + get_i(); // OGCG: ret ptr %[[GET_GLOB]] extern thread_local int definitely_inited = 5; -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW17definitely_inited", "_ZTH17definitely_inited"> @definitely_inited = #cir.int<5> : !s32i -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW17definitely_inited", "_ZTH17definitely_inited"> @definitely_inited = #cir.int<5> : !s32i +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW17definitely_inited", "_ZTH17definitely_inited"> @definitely_inited = #cir.int<5> : !s32i +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW17definitely_inited", "_ZTH17definitely_inited"> @definitely_inited = #cir.int<5> : !s32i extern thread_local int definitely_inited_dyn = get_i(); -// CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> @definitely_inited_dyn = ctor : !s32i { +// CIR-BEFORE-LPP: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> @definitely_inited_dyn = ctor : !s32i { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @definitely_inited_dyn : !cir.ptr<!s32i> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) // CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i> // CIR-BEFORE-LPP: } -// CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> @definitely_inited_dyn = #cir.int<0> : !s32i +// CIR: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> @definitely_inited_dyn = #cir.int<0> : !s32i // CIR: cir.func internal private @[[DEF_INITED_DYN]]() { // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @definitely_inited_dyn : !cir.ptr<!s32i> // CIR: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) @@ -247,8 +247,8 @@ extern thread_local int definitely_inited_dyn = get_i(); // LLVM-BOTH: ret void extern thread_local int maybe_inited; -// CIR-BEFORE-LPP: cir.global "private" external tls_dyn dyn_tls_refs = <"_ZTW12maybe_inited", "_ZTH12maybe_inited"> @maybe_inited : !s32i -// CIR: cir.global "private" external tls_dyn dyn_tls_refs = <"_ZTW12maybe_inited", "_ZTH12maybe_inited"> @maybe_inited : !s32i +// CIR-BEFORE-LPP: cir.global "private" external tls_model = <tls_dyn> tls_refs = <"_ZTW12maybe_inited", "_ZTH12maybe_inited"> @maybe_inited : !s32i +// CIR: cir.global "private" external tls_model = <tls_dyn> tls_refs = <"_ZTW12maybe_inited", "_ZTH12maybe_inited"> @maybe_inited : !s32i void uses() { auto a = tls_int; diff --git a/clang/test/CIR/CodeGen/global-tls-templates.cpp b/clang/test/CIR/CodeGen/global-tls-templates.cpp index 81bb2e54334a6..cfec92049c8e6 100644 --- a/clang/test/CIR/CodeGen/global-tls-templates.cpp +++ b/clang/test/CIR/CodeGen/global-tls-templates.cpp @@ -13,13 +13,13 @@ struct CtorDtor { template<typename T> thread_local T tls_templ = {get_i()}; -// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_dyn dyn_tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> @_Z9tls_templIiE = ctor : !s32i { +// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_model = <tls_dyn> tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> @_Z9tls_templIiE = ctor : !s32i { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @_Z9tls_templIiE : !cir.ptr<!s32i> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) // CIR-BEFORE-LPP: cir.store{{.*}} %[[CALL]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i> // CIR-BEFORE-LPP: } // -// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_dyn dyn_tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", "_ZGV9tls_templI8CtorDtorE"> @_Z9tls_templI8CtorDtorE = ctor : !rec_CtorDtor { +// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_model = <tls_dyn> tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", "_ZGV9tls_templI8CtorDtorE"> @_Z9tls_templI8CtorDtorE = ctor : !rec_CtorDtor { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @_Z9tls_templI8CtorDtorE : !cir.ptr<!rec_CtorDtor> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : (!cir.ptr<!rec_CtorDtor> @@ -38,7 +38,7 @@ thread_local T tls_templ = {get_i()}; // Alias: Ctor/Dtor: // CIR: cir.func linkonce_odr @_ZTH9tls_templI8CtorDtorE() alias(@[[CTOR_DTOR_INIT:[^)]*]]) // TLS Guard: Ctor/Dtor: -// CIR: cir.global "private" linkonce_odr comdat tls_dyn @_ZGV9tls_templI8CtorDtorE = #cir.int<0> : !s64i +// CIR: cir.global "private" linkonce_odr comdat tls_model = <tls_dyn> @_ZGV9tls_templI8CtorDtorE = #cir.int<0> : !s64i // Wrapper: int // CIR-LABEL: cir.func comdat weak_odr private hidden @_ZTW9tls_templIiE() -> !cir.ptr<!s32i> @@ -50,10 +50,10 @@ thread_local T tls_templ = {get_i()}; // Alias: int // CIR: cir.func linkonce_odr @_ZTH9tls_templIiE() alias(@[[INT_INIT:[^)]*]]) // TLS Guard: int -// CIR: cir.global "private" linkonce_odr comdat tls_dyn @_ZGV9tls_templIiE = #cir.int<0> : !s64i +// CIR: cir.global "private" linkonce_odr comdat tls_model = <tls_dyn> @_ZGV9tls_templIiE = #cir.int<0> : !s64i // Global: int -// CIR: cir.global linkonce_odr comdat tls_dyn dyn_tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> @_Z9tls_templIiE = #cir.int<0> : !s32i +// CIR: cir.global linkonce_odr comdat tls_model = <tls_dyn> tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> @_Z9tls_templIiE = #cir.int<0> : !s32i // Init Func: int // CIR: cir.func internal private @[[INT_INIT]]() { @@ -74,7 +74,7 @@ thread_local T tls_templ = {get_i()}; // Global: Ctor/Dotr: -// CIR: cir.global linkonce_odr comdat tls_dyn dyn_tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", "_ZGV9tls_templI8CtorDtorE"> @_Z9tls_templI8CtorDtorE = #cir.zero : !rec_CtorDtor +// CIR: cir.global linkonce_odr comdat tls_model = <tls_dyn> tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", "_ZGV9tls_templI8CtorDtorE"> @_Z9tls_templI8CtorDtorE = #cir.zero : !rec_CtorDtor // Init Func: Ctor/Dtor: // CIR: cir.func internal private @[[CTOR_DTOR_INIT]]() { diff --git a/clang/test/CIR/CodeGen/thread-local-in-func.cpp b/clang/test/CIR/CodeGen/thread-local-in-func.cpp index 0d8466ab41471..04542164dade2 100644 --- a/clang/test/CIR/CodeGen/thread-local-in-func.cpp +++ b/clang/test/CIR/CodeGen/thread-local-in-func.cpp @@ -4,32 +4,32 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OGCG,LLVM-BOTH // Guard variables. -// CIR-DAG: cir.global "private" internal tls_dyn dso_local @_ZGVZ13test_ctordtoriE4init = #cir.int<0> : !s8i +// CIR-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ13test_ctordtoriE4init = #cir.int<0> : !s8i // LLVM-BOTH-DAG: @_ZGVZ13test_ctordtoriE4init = internal thread_local global i8 0 -// CIR-DAG: cir.global "private" internal tls_dyn dso_local @_ZGVZ13test_ctordtoriE10const_init = #cir.int<0> : !s8i +// CIR-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ13test_ctordtoriE10const_init = #cir.int<0> : !s8i // LLVM-BOTH-DAG: @_ZGVZ13test_ctordtoriE10const_init = internal thread_local global i8 0 -// CIR-DAG: cir.global "private" internal tls_dyn dso_local @_ZGVZ9test_dtoriE10const_init = #cir.int<0> : !s8i +// CIR-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ9test_dtoriE10const_init = #cir.int<0> : !s8i // LLVM-BOTH-DAG: @_ZGVZ9test_dtoriE10const_init = internal thread_local global i8 0 -// CIR-DAG: cir.global "private" internal tls_dyn dso_local @_ZGVZ9test_ctoriE4init = #cir.int<0> : !s8i +// CIR-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ9test_ctoriE4init = #cir.int<0> : !s8i // LLVM-BOTH-DAG: @_ZGVZ9test_ctoriE4init = internal thread_local global i8 0 -// CIR-DAG: cir.global "private" internal tls_dyn dso_local @_ZGVZ9test_ctoriE10const_init = #cir.int<0> : !s8i +// CIR-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ9test_ctoriE10const_init = #cir.int<0> : !s8i // LLVM-BOTH-DAG: @_ZGVZ9test_ctoriE10const_init = internal thread_local global i8 0 -// CIR-DAG: cir.global "private" internal tls_dyn dso_local @_ZGVZ8test_intiE4init = #cir.int<0> : !s8i +// CIR-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ8test_intiE4init = #cir.int<0> : !s8i // LLVM-BOTH-DAG: @_ZGVZ8test_intiE4init = internal thread_local global i8 0 -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local static_local_guard<"_ZGVZ13test_ctordtoriE4init"> @_ZZ13test_ctordtoriE4init = #cir.zero : !rec_CtorDtor +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ13test_ctordtoriE4init"> @_ZZ13test_ctordtoriE4init = #cir.zero : !rec_CtorDtor // LLVM-BOTH-DAG: @_ZZ13test_ctordtoriE4init = internal thread_local global %struct.CtorDtor zeroinitializer -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local static_local_guard<"_ZGVZ13test_ctordtoriE10const_init"> @_ZZ13test_ctordtoriE10const_init = #cir.zero : !rec_CtorDtor +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ13test_ctordtoriE10const_init"> @_ZZ13test_ctordtoriE10const_init = #cir.zero : !rec_CtorDtor // LLVM-BOTH-DAG: @_ZZ13test_ctordtoriE10const_init = internal thread_local global %struct.CtorDtor zeroinitializer -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local static_local_guard<"_ZGVZ9test_dtoriE10const_init"> @_ZZ9test_dtoriE10const_init = #cir.zero : !rec_Dtor +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ9test_dtoriE10const_init"> @_ZZ9test_dtoriE10const_init = #cir.zero : !rec_Dtor // LLVM-BOTH-DAG: @_ZZ9test_dtoriE10const_init = internal thread_local global %struct.Dtor zeroinitializer -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local static_local_guard<"_ZGVZ9test_ctoriE4init"> @_ZZ9test_ctoriE4init = #cir.zero : !rec_Ctor +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ9test_ctoriE4init"> @_ZZ9test_ctoriE4init = #cir.zero : !rec_Ctor // LLVM-BOTH-DAG: @_ZZ9test_ctoriE4init = internal thread_local global %struct.Ctor zeroinitializer -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local static_local_guard<"_ZGVZ9test_ctoriE10const_init"> @_ZZ9test_ctoriE10const_init = #cir.zero : !rec_Ctor +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ9test_ctoriE10const_init"> @_ZZ9test_ctoriE10const_init = #cir.zero : !rec_Ctor // LLVM-BOTH-DAG: @_ZZ9test_ctoriE10const_init = internal thread_local global %struct.Ctor zeroinitializer -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local static_local_guard<"_ZGVZ8test_intiE4init"> @_ZZ8test_intiE4init = #cir.int<0> : !s32i +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ8test_intiE4init"> @_ZZ8test_intiE4init = #cir.int<0> : !s32i // LLVM-BOTH-DAG: @_ZZ8test_intiE4init = internal thread_local global i32 0 -// CIR-BOTH-DAG: cir.global "private" internal tls_dyn dso_local @_ZZ8test_intiE10const_init = #cir.int<5> : !s32i +// CIR-BOTH-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZZ8test_intiE10const_init = #cir.int<5> : !s32i // LLVM-BOTH-DAG: @_ZZ8test_intiE10const_init = internal thread_local global i32 5 int get_i(); diff --git a/clang/test/CIR/CodeGen/tls-model-func-scope.cpp b/clang/test/CIR/CodeGen/tls-model-func-scope.cpp new file mode 100644 index 0000000000000..ca7408fba47b1 --- /dev/null +++ b/clang/test/CIR/CodeGen/tls-model-func-scope.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-cir -o - | FileCheck %s -check-prefix=CIR-GD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-llvm -fclangir -o - | FileCheck %s -check-prefix=LLVM-GD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=LLVM-GD + +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=global-dynamic -emit-cir -o - | FileCheck %s -check-prefix=CIR-GD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=global-dynamic -emit-llvm -fclangir -o - | FileCheck %s -check-prefix=LLVM-GD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=LLVM-GD + +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-dynamic -emit-cir -o - | FileCheck %s -check-prefix=CIR-LD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-dynamic -emit-llvm -fclangir -o - | FileCheck %s -check-prefix=LLVM-LD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=LLVM-LD + +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=initial-exec -emit-cir -o - | FileCheck %s -check-prefix=CIR-IE +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=initial-exec -emit-llvm -fclangir -o - | FileCheck %s -check-prefix=LLVM-IE +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=LLVM-IE + +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-exec -emit-cir -o - | FileCheck %s -check-prefix=CIR-LE +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-exec -emit-llvm -fclangir -o - | FileCheck %s -check-prefix=LLVM-LE +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=LLVM-LE + +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -femulated-tls -emit-cir -o - 2>&1 | FileCheck %s -check-prefix=CIR-GD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -femulated-tls -emit-llvm -fclangir -o - 2>&1 | FileCheck %s -check-prefix=LLVM-GD +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -femulated-tls -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=LLVM-GD + +int init(); + +void func() { + thread_local int default_tls_mode = init(); + + __attribute__((tls_model("initial-exec"))) + thread_local int override_tls_mode = init(); +} +// CIR-GD: module {{.*}} attributes +// CIR-GD-SAME: cir.default_tls_model = #cir.tls_model<tls_dyn> +// CIR-GD: cir.global "private" internal tls_model = <tls_init_exec> dso_local @_ZGVZ4funcvE17override_tls_mode = #cir.int<0> : !s8i +// CIR-GD: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZGVZ4funcvE16default_tls_mode = #cir.int<0> : !s8i +// CIR-GD: cir.global "private" internal tls_model = <tls_init_exec> dso_local static_local_guard<"_ZGVZ4funcvE17override_tls_mode"> @_ZZ4funcvE17override_tls_mode = #cir.int<0> : !s32i +// CIR-GD: cir.global "private" internal tls_model = <tls_dyn> dso_local static_local_guard<"_ZGVZ4funcvE16default_tls_mode"> @_ZZ4funcvE16default_tls_mode = #cir.int<0> : !s32i + +// LLVM-GD-DAG: @_ZGVZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i8 0 +// LLVM-GD-DAG: @_ZGVZ4funcvE16default_tls_mode = internal thread_local global i8 0 +// LLVM-GD-DAG: @_ZZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i32 0 +// LLVM-GD-DAG: @_ZZ4funcvE16default_tls_mode = internal thread_local global i32 0 + +// CIR-LD: module {{.*}} attributes +// CIR-LD-SAME: cir.default_tls_model = #cir.tls_model<tls_local_dyn> +// CIR-LD: cir.global "private" internal tls_model = <tls_init_exec> dso_local @_ZGVZ4funcvE17override_tls_mode = #cir.int<0> : !s8i +// CIR-LD: cir.global "private" internal tls_model = <tls_local_dyn> dso_local @_ZGVZ4funcvE16default_tls_mode = #cir.int<0> : !s8i +// CIR-LD: cir.global "private" internal tls_model = <tls_init_exec> dso_local static_local_guard<"_ZGVZ4funcvE17override_tls_mode"> @_ZZ4funcvE17override_tls_mode = #cir.int<0> : !s32i +// CIR-LD: cir.global "private" internal tls_model = <tls_local_dyn> dso_local static_local_guard<"_ZGVZ4funcvE16default_tls_mode"> @_ZZ4funcvE16default_tls_mode = #cir.int<0> : !s32i + +// LLVM-LD-DAG: @_ZGVZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i8 0 +// LLVM-LD-DAG: @_ZGVZ4funcvE16default_tls_mode = internal thread_local(localdynamic) global i8 0 +// LLVM-LD-DAG: @_ZZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i32 0 +// LLVM-LD-DAG: @_ZZ4funcvE16default_tls_mode = internal thread_local(localdynamic) global i32 0 + +// CIR-IE: module {{.*}} attributes +// CIR-IE-SAME: cir.default_tls_model = #cir.tls_model<tls_init_exec> +// CIR-IE: cir.global "private" internal tls_model = <tls_init_exec> dso_local @_ZGVZ4funcvE17override_tls_mode = #cir.int<0> : !s8i +// CIR-IE: cir.global "private" internal tls_model = <tls_init_exec> dso_local @_ZGVZ4funcvE16default_tls_mode = #cir.int<0> : !s8i +// CIR-IE: cir.global "private" internal tls_model = <tls_init_exec> dso_local static_local_guard<"_ZGVZ4funcvE17override_tls_mode"> @_ZZ4funcvE17override_tls_mode = #cir.int<0> : !s32i +// CIR-IE: cir.global "private" internal tls_model = <tls_init_exec> dso_local static_local_guard<"_ZGVZ4funcvE16default_tls_mode"> @_ZZ4funcvE16default_tls_mode = #cir.int<0> : !s32i + +// LLVM-IE-DAG: @_ZGVZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i8 0 +// LLVM-IE-DAG: @_ZGVZ4funcvE16default_tls_mode = internal thread_local(initialexec) global i8 0 +// LLVM-IE-DAG: @_ZZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i32 0 +// LLVM-IE-DAG: @_ZZ4funcvE16default_tls_mode = internal thread_local(initialexec) global i32 0 + +// CIR-LE: module {{.*}} attributes +// CIR-LE-SAME: cir.default_tls_model = #cir.tls_model<tls_local_exec> +// CIR-LE: cir.global "private" internal tls_model = <tls_init_exec> dso_local @_ZGVZ4funcvE17override_tls_mode = #cir.int<0> : !s8i +// CIR-LE: cir.global "private" internal tls_model = <tls_local_exec> dso_local @_ZGVZ4funcvE16default_tls_mode = #cir.int<0> : !s8i +// CIR-LE: cir.global "private" internal tls_model = <tls_init_exec> dso_local static_local_guard<"_ZGVZ4funcvE17override_tls_mode"> @_ZZ4funcvE17override_tls_mode = #cir.int<0> : !s32i +// CIR-LE: cir.global "private" internal tls_model = <tls_local_exec> dso_local static_local_guard<"_ZGVZ4funcvE16default_tls_mode"> @_ZZ4funcvE16default_tls_mode = #cir.int<0> : !s32i + +// LLVM-LE-DAG: @_ZGVZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i8 0 +// LLVM-LE-DAG: @_ZGVZ4funcvE16default_tls_mode = internal thread_local(localexec) global i8 0 +// LLVM-LE-DAG: @_ZZ4funcvE17override_tls_mode = internal thread_local(initialexec) global i32 0 +// LLVM-LE-DAG: @_ZZ4funcvE16default_tls_mode = internal thread_local(localexec) global i32 0 diff --git a/clang/test/CIR/CodeGen/tls-model.cpp b/clang/test/CIR/CodeGen/tls-model.cpp index 471891a16ca5b..437e24c3cfc77 100644 --- a/clang/test/CIR/CodeGen/tls-model.cpp +++ b/clang/test/CIR/CodeGen/tls-model.cpp @@ -1,4 +1,3 @@ - // RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-cir -o - | FileCheck %s -check-prefix=CIR-GD // RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-llvm -fclangir -o - | FileCheck %s -check-prefix=LLVM-GD // RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=LLVM-GD @@ -46,14 +45,16 @@ struct T thread_local t1; // Note that unlike normal C uninitialized global variables, // uninitialized TLS variables do NOT have COMMON linkage. +// CIR-GD: module {{.*}} attributes +// CIR-GD-SAME: cir.default_tls_model = #cir.tls_model<tls_dyn> // CIR-GD-DAG: cir.global external @z1 = #cir.int<0> : !s32i {alignment = 4 : i64} // CIR-GD-DAG: cir.global external @z2 = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-GD-DAG: cir.global external tls_dyn dyn_tls_refs = <"_ZTW1x", "_ZTH1x"> @x = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-GD-DAG: cir.global "private" internal tls_dyn dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-GD-DAG: cir.global external tls_init_exec @z = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-GD-DAG: cir.global external tls_dyn dyn_tls_refs = <"_ZTW2s1", "_ZTH2s1"> @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} -// CIR-GD-DAG: cir.global external tls_dyn dyn_tls_refs = <"_ZTW2t1", "_ZTH2t1"> @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} -// CIR-GD-DAG: cir.global internal tls_dyn @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} +// CIR-GD-DAG: cir.global external tls_model = <tls_dyn> @x = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-GD-DAG: cir.global "private" internal tls_model = <tls_dyn> dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-GD-DAG: cir.global external tls_model = <tls_init_exec> @z = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-GD-DAG: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW2s1", "_ZTH2s1"> @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-GD-DAG: cir.global external tls_model = <tls_dyn> tls_refs = <"_ZTW2t1", "_ZTH2t1"> @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-GD-DAG: cir.global internal tls_model = <tls_dyn> @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} // LLVM-GD-DAG: @z1 ={{.*}} global i32 0 // LLVM-GD-DAG: @z2 ={{.*}} global i32 0 @@ -61,19 +62,23 @@ struct T thread_local t1; // LLVM-GD-DAG: @_ZZ1fvE1y = internal thread_local global i32 0 // LLVM-GD-DAG: @z ={{.*}} thread_local(initialexec) global i32 0 // LLVM-GD-DAG: @s1 ={{.*}} thread_local global %struct.S zeroinitializer +// LLVM-GD-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2s1() +// LLVM-GD-DAG: @_ZTH2s1 = alias void (), ptr @__tls_init // LLVM-GD-DAG: @t1 ={{.*}} thread_local global %struct.T zeroinitializer +// LLVM-GD-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2t1() +// LLVM-GD-DAG: @_ZTH2t1 = alias void (), ptr @__tls_init // LLVM-GD-DAG: @__tls_guard = internal thread_local global i8 0 +// CIR-LD: module {{.*}} attributes +// CIR-LD-SAME: cir.default_tls_model = #cir.tls_model<tls_local_dyn> // CIR-LD-DAG: cir.global external @z1 = #cir.int<0> : !s32i {alignment = 4 : i64} // CIR-LD-DAG: cir.global external @z2 = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LD-DAG: cir.global external tls_local_dyn @x = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LD-DAG: cir.global "private" internal tls_local_dyn dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LD-DAG: cir.global external tls_init_exec @z = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LD-DAG: cir.global external tls_local_dyn @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} -// CIR-LD-DAG: cir.global external tls_local_dyn @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} -// FIXME: our lowering for tls only emits the guard for tls_dyn, so this doesn't -// appear. -// cir.global internal tls_local_dyn @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} +// CIR-LD-DAG: cir.global external tls_model = <tls_local_dyn> @x = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-LD-DAG: cir.global "private" internal tls_model = <tls_local_dyn> dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-LD-DAG: cir.global external tls_model = <tls_init_exec> @z = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-LD-DAG: cir.global external tls_model = <tls_local_dyn> tls_refs = <"_ZTW2s1", "_ZTH2s1"> @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-LD-DAG: cir.global external tls_model = <tls_local_dyn> tls_refs = <"_ZTW2t1", "_ZTH2t1"> @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-LD-DAG: cir.global internal tls_model = <tls_local_dyn> @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} // LLVM-LD-DAG: @z1 ={{.*}} global i32 0 // LLVM-LD-DAG: @z2 ={{.*}} global i32 0 @@ -81,21 +86,23 @@ struct T thread_local t1; // LLVM-LD-DAG: @_ZZ1fvE1y = internal thread_local(localdynamic) global i32 0 // LLVM-LD-DAG: @z ={{.*}} thread_local(initialexec) global i32 0 // LLVM-LD-DAG: @s1 ={{.*}} thread_local(localdynamic) global %struct.S zeroinitializer +// LLVM-LD-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2s1() +// LLVM-LD-DAG: @_ZTH2s1 = alias void (), ptr @__tls_init // LLVM-LD-DAG: @t1 ={{.*}} thread_local(localdynamic) global %struct.T zeroinitializer -// FIXME: our lowering for tls only emits the guard for tls_dyn, so this doesn't -// appear. -// @__tls_guard = internal thread_local(localdynamic) global i8 0 +// LLVM-LD-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2t1() +// LLVM-LD-DAG: @_ZTH2t1 = alias void (), ptr @__tls_init +// LLVM-LD-DAG: @__tls_guard = internal thread_local(localdynamic) global i8 0 +// CIR-IE: module {{.*}} attributes +// CIR-IE-SAME: cir.default_tls_model = #cir.tls_model<tls_init_exec> // CIR-IE-DAG: cir.global external @z1 = #cir.int<0> : !s32i {alignment = 4 : i64} // CIR-IE-DAG: cir.global external @z2 = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-IE-DAG: cir.global external tls_init_exec @x = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-IE-DAG: cir.global "private" internal tls_init_exec dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-IE-DAG: cir.global external tls_init_exec @z = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-IE-DAG: cir.global external tls_init_exec @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} -// CIR-IE-DAG: cir.global external tls_init_exec @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} -// FIXME: our lowering for tls only emits the guard for tls_dyn, so this doesn't -// appear. -// cir.global internal tls_init_exec @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} +// CIR-IE-DAG: cir.global external tls_model = <tls_init_exec> @x = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-IE-DAG: cir.global "private" internal tls_model = <tls_init_exec> dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-IE-DAG: cir.global external tls_model = <tls_init_exec> @z = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-IE-DAG: cir.global external tls_model = <tls_init_exec> tls_refs = <"_ZTW2s1", "_ZTH2s1"> @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-IE-DAG: cir.global external tls_model = <tls_init_exec> tls_refs = <"_ZTW2t1", "_ZTH2t1"> @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-IE-DAG: cir.global internal tls_model = <tls_init_exec> @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} // LLVM-IE-DAG: @z1 ={{.*}} global i32 0 // LLVM-IE-DAG: @z2 ={{.*}} global i32 0 @@ -103,21 +110,23 @@ struct T thread_local t1; // LLVM-IE-DAG: @_ZZ1fvE1y = internal thread_local(initialexec) global i32 0 // LLVM-IE-DAG: @z ={{.*}} thread_local(initialexec) global i32 0 // LLVM-IE-DAG: @s1 ={{.*}} thread_local(initialexec) global %struct.S zeroinitializer +// LLVM-IE-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2s1() +// LLVM-IE-DAG: @_ZTH2s1 = alias void (), ptr @__tls_init // LLVM-IE-DAG: @t1 ={{.*}} thread_local(initialexec) global %struct.T zeroinitializer -// FIXME: our lowering for tls only emits the guard for tls_dyn, so this doesn't -// appear. -// @__tls_guard = internal thread_local(initialexec) global i8 0 +// LLVM-IE-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2t1() +// LLVM-IE-DAG: @_ZTH2t1 = alias void (), ptr @__tls_init +// LLVM-IE-DAG: @__tls_guard = internal thread_local(initialexec) global i8 0 +// CIR-LE: module {{.*}} attributes +// CIR-LE-SAME: cir.default_tls_model = #cir.tls_model<tls_local_exec> // CIR-LE-DAG: cir.global external @z1 = #cir.int<0> : !s32i {alignment = 4 : i64} // CIR-LE-DAG: cir.global external @z2 = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LE-DAG: cir.global external tls_local_exec @x = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LE-DAG: cir.global "private" internal tls_local_exec dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LE-DAG: cir.global external tls_init_exec @z = #cir.int<0> : !s32i {alignment = 4 : i64} -// CIR-LE-DAG: cir.global external tls_local_exec @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} -// CIR-LE-DAG: cir.global external tls_local_exec @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} -// FIXME: our lowering for tls only emits the guard for tls_dyn, so this doesn't -// appear. -// cir.global internal tls_local_exec @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} +// CIR-LE-DAG: cir.global external tls_model = <tls_local_exec> @x = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-LE-DAG: cir.global "private" internal tls_model = <tls_local_exec> dso_local @_ZZ1fvE1y = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-LE-DAG: cir.global external tls_model = <tls_init_exec> @z = #cir.int<0> : !s32i {alignment = 4 : i64} +// CIR-LE-DAG: cir.global external tls_model = <tls_local_exec> tls_refs = <"_ZTW2s1", "_ZTH2s1"> @s1 = #cir.zero : !rec_S {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-LE-DAG: cir.global external tls_model = <tls_local_exec> tls_refs = <"_ZTW2t1", "_ZTH2t1"> @t1 = #cir.zero : !rec_T {alignment = 1 : i64, ast = #cir.var.decl.ast} +// CIR-LE-DAG: cir.global internal tls_model = <tls_local_exec> @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} // LLVM-LE-DAG: @z1 ={{.*}} global i32 0 // LLVM-LE-DAG: @z2 ={{.*}} global i32 0 @@ -125,7 +134,9 @@ struct T thread_local t1; // LLVM-LE-DAG: @_ZZ1fvE1y = internal thread_local(localexec) global i32 0 // LLVM-LE-DAG: @z ={{.*}} thread_local(initialexec) global i32 0 // LLVM-LE-DAG: @s1 ={{.*}} thread_local(localexec) global %struct.S zeroinitializer +// LLVM-LE-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2s1() +// LLVM-LE-DAG: @_ZTH2s1 = alias void (), ptr @__tls_init // LLVM-LE-DAG: @t1 ={{.*}} thread_local(localexec) global %struct.T zeroinitializer -// FIXME: our lowering for tls only emits the guard for tls_dyn, so this doesn't -// appear. -// @__tls_guard = internal thread_local(localexec) global i8 0 +// LLVM-LE-DAG: define weak_odr hidden {{.*}}ptr @_ZTW2t1() +// LLVM-LE-DAG: @_ZTH2t1 = alias void (), ptr @__tls_init +// LLVM-LE-DAG: @__tls_guard = internal thread_local(localexec) global i8 0 diff --git a/clang/test/CIR/CodeGen/tls.c b/clang/test/CIR/CodeGen/tls.c index 582a716f0fa73..5fa7f0d9e527d 100644 --- a/clang/test/CIR/CodeGen/tls.c +++ b/clang/test/CIR/CodeGen/tls.c @@ -6,10 +6,10 @@ // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ogcg.ll %s extern __thread int b; -// CIR: cir.global "private" external tls_dyn @b : !s32i +// CIR: cir.global "private" external tls_model = <tls_dyn> @b : !s32i __thread int a; -// CIR: cir.global external tls_dyn @a = #cir.int<0> : !s32i +// CIR: cir.global external tls_model = <tls_dyn> @a = #cir.int<0> : !s32i int c(void) { return *&b; } // CIR: cir.func no_inline dso_local @c() -> !s32i diff --git a/clang/test/CIR/IR/global.cir b/clang/test/CIR/IR/global.cir index fe3a0b95c65f3..8af73871c2725 100644 --- a/clang/test/CIR/IR/global.cir +++ b/clang/test/CIR/IR/global.cir @@ -49,6 +49,10 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { cir.global external @fp = #cir.ptr<null> : !cir.ptr<!cir.func<()>> cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i) -> !s32i>> cir.global external @fpvar = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i, ...)>> + cir.global external tls_model = <tls_dyn> @tls1 = #cir.int<0> : !s8i + cir.global external tls_model = <tls_local_dyn> @tls2 = #cir.int<0> : !s8i + cir.global external tls_model = <tls_init_exec> @tls3 = #cir.int<0> : !s8i + cir.global external tls_model = <tls_local_exec> @tls4 = #cir.int<0> : !s8i } // CHECK: cir.global external @c = #cir.int<0> : !s8i @@ -87,3 +91,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { // CHECK: cir.global external @fp = #cir.ptr<null> : !cir.ptr<!cir.func<()>> // CHECK: cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i) -> !s32i>> // CHECK: cir.global external @fpvar = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i, ...)>> +// CHECK: cir.global external tls_model = <tls_dyn> @tls1 = #cir.int<0> : !s8i +// CHECK: cir.global external tls_model = <tls_local_dyn> @tls2 = #cir.int<0> : !s8i +// CHECK: cir.global external tls_model = <tls_init_exec> @tls3 = #cir.int<0> : !s8i +// CHECK: cir.global external tls_model = <tls_local_exec> @tls4 = #cir.int<0> : !s8i diff --git a/clang/test/CIR/IR/invalid-tls.cir b/clang/test/CIR/IR/invalid-tls.cir index e33b7070eb790..837fedec8514e 100644 --- a/clang/test/CIR/IR/invalid-tls.cir +++ b/clang/test/CIR/IR/invalid-tls.cir @@ -16,8 +16,8 @@ module { !s32i = !cir.int<s, 32> module { - // expected-error@+1{{op cannot have both static local and dynamic tls references}} -cir.global "private" internal tls_dyn dyn_tls_refs = <"asdf", "asdf", "asdf"> static_local_guard<"asdf"> @_ZZ1fvE1y : !s32i + // expected-error@+1{{op cannot have both static local and tls references}} +cir.global "private" internal tls_model = <tls_dyn> tls_refs = <"asdf", "asdf", "asdf"> static_local_guard<"asdf"> @_ZZ1fvE1y : !s32i } // ----- @@ -25,7 +25,16 @@ cir.global "private" internal tls_dyn dyn_tls_refs = <"asdf", "asdf", "asdf"> st !s32i = !cir.int<s, 32> module { - // expected-error@+1{{'dyn_tls_refs' only valid for dynamic tls}} -cir.global "private" internal tls_local_dyn dyn_tls_refs = <"asdf", "asdf", "asdf"> @_ZZ1fvE1y : !s32i + // expected-error@+1{{'tls_refs' only valid for tls}} +cir.global "private" internal tls_refs = <"asdf", "asdf", "asdf"> @_ZZ1fvE1y : !s32i } +// ----- + +!s32i = !cir.int<s, 32> + +module { + // expected-error@+2{{custom op 'cir.global' expected ::cir::TLSModel to be one of: tls_dyn, tls_local_dyn, tls_init_exec, tls_local_exec}} + // expected-error@+1{{custom op 'cir.global' failed to parse CIR_TLSModelAttr parameter 'value' which is to be a `::cir::TLSModel}} +cir.global "private" internal tls_model = <invalid_tls_dyn> tls_refs = <"asdf", "asdf", "asdf"> @_ZZ1fvE1y : !s32i +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
