Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2046,10 +2046,16 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy,
TheModule.getDataLayout().getProgramAddressSpace());
llvm::PointerType *AssocDataPtrTy =
llvm::PointerType::getUnqual(getLLVMContext());

// Get the type of a ctor entry, { i32, void ()*, i8* }.
llvm::StructType *CtorStructTy = llvm::StructType::get(
Int32Ty, CtorPFTy, VoidPtrTy);
// Get the type of a ctor entry, { i32, program void ()*, i8* }.
// Note that we unconditionally emit an unqualified pointer to the associated
// data - this is intentional as this is a fake global, serving only as a
// lifetime extension hook; this must match the type we use in the llvm.used
// and llvm.compiler.used arrays.
llvm::StructType *CtorStructTy =
llvm::StructType::get(Int32Ty, CtorPFTy, AssocDataPtrTy);

// Construct the constructor and destructor arrays.
ConstantInitBuilder builder(*this);
Expand All @@ -2059,16 +2065,17 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
ctor.addInt(Int32Ty, I.Priority);
ctor.add(I.Initializer);
if (I.AssociatedData)
ctor.add(I.AssociatedData);
ctor.add(
llvm::ConstantExpr::getPointerCast(I.AssociatedData, AssocDataPtrTy));
else
ctor.addNullPointer(VoidPtrTy);
ctor.addNullPointer(AssocDataPtrTy);
ctor.finishAndAddTo(ctors);
}

auto list =
ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
/*constant*/ false,
llvm::GlobalValue::AppendingLinkage);
auto list = ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
/*constant*/ false,
llvm::GlobalValue::AppendingLinkage,
GlobalsInt8PtrTy->getAddressSpace());

// The LTO linker doesn't seem to like it when we set an alignment
// on appending variables. Take it off as a workaround.
Expand Down
2 changes: 2 additions & 0 deletions clang/test/CodeGen/asan-constructor.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fsanitize=address -emit-llvm -o - %s | FileCheck %s --check-prefix=EMSCRIPTEN
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fsanitize=address -emit-llvm -o - %s | FileCheck %s --check-prefix=GLOBALAS

// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @asan.module_ctor, ptr null }]
// EMSCRIPTEN: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 50, ptr @asan.module_ctor, ptr null }]
// GLOBALAS: @llvm.global_ctors = appending addrspace(1) global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @asan.module_ctor, ptr null }]
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ std::initializer_list<int> thread_local x = {1, 2, 3, 4};
// AMDGCN: @[[REFTMP1:.*]] = private addrspace(4) constant [2 x i32] [i32 42, i32 43], align 4
// AMDGCN: @[[REFTMP2:.*]] = private addrspace(4) constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4

// CHECK: appending global
// X86: appending global
// AMDGCN: appending addrspace(1) global

// thread_local initializer:
// X86-LABEL: define internal void @__cxx_global_var_init
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck --check-prefix=ELF --check-prefix=ALL %s
// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck --check-prefix=MACHO --check-prefix=ALL %s
// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -fdeclspec -DSELECTANY -o - | FileCheck --check-prefix=ELF-SELECTANY %s
// RUN: %clang_cc1 %s -std=c++1y -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefix=GLOBALAS-ELF %s
// RUN: %clang_cc1 %s -std=c++1y -triple=amdgcn-amd-amdhsa -emit-llvm -fdeclspec -DSELECTANY -o - | FileCheck --check-prefix=GLOBALAS-ELF-SELECTANY %s

#ifdef SELECTANY
struct S {
Expand All @@ -12,6 +14,7 @@ int f();

// ELF-SELECTANY: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @selectany }]
// ELF-SELECTANY: @llvm.used = appending global [1 x ptr] [ptr @selectany]
// GLOBALAS-ELF-SELECTANY: @llvm.global_ctors = appending addrspace(1) global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr addrspacecast (ptr addrspace(1) @selectany to ptr) }]
int __declspec(selectany) selectany = f();

#else
Expand All @@ -30,6 +33,7 @@ template<> int A<char>::a;
template<> int A<bool>::a = 10;

// ALL: @llvm.global_ctors = appending global [16 x { i32, ptr, ptr }]
// GLOBALAS-ELF: @llvm.global_ctors = appending addrspace(1) global [16 x { i32, ptr, ptr }]

// ELF: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered:[^,]*]], ptr @_ZN1AIsE1aE },
// MACHO: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered:[^,]*]], ptr null },
Expand Down Expand Up @@ -73,7 +77,7 @@ template<> int A<bool>::a = 10;
// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered22:[^,]*]], ptr null },

// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr @_ZN4Fib2ILi5EE1aE },
// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr null },
// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr null },

// ALL: { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, ptr null }]

Expand Down
4 changes: 2 additions & 2 deletions clang/test/OpenMP/amdgcn_target_global_constructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ S A;

#endif
//.
// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_amdgcn_target_global_constructor.cpp, ptr null }]
// CHECK: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__dtor_A, ptr null }]
// CHECK: @llvm.global_ctors = appending addrspace(1) global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_amdgcn_target_global_constructor.cpp, ptr null }]
// CHECK: @llvm.global_dtors = appending addrspace(1) global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__dtor_A, ptr null }]
//.
// CHECK-LABEL: define {{[^@]+}}@__cxx_global_var_init
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
Expand Down
48 changes: 27 additions & 21 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ added in the future:
not be used lightly but only for specific situations such as an
alternative to the *register pinning* performance technique often
used when implementing functional programming languages. At the
moment only X86, AArch64, and RISCV support this convention. The
moment only X86, AArch64, and RISCV support this convention. The
following limitations exist:

- On *X86-32* only up to 4 bit type parameters are supported. No
Expand Down Expand Up @@ -685,10 +685,10 @@ implementation defined, the optimizer can't do the latter. The former is
challenging as many commonly expected properties, such as
``ptrtoint(v)-ptrtoint(v) == 0``, don't hold for non-integral types.
Similar restrictions apply to intrinsics that might examine the pointer bits,
such as :ref:`llvm.ptrmask<int_ptrmask>`.
such as :ref:`llvm.ptrmask<int_ptrmask>`.

The alignment information provided by the frontend for a non-integral pointer
(typically using attributes or metadata) must be valid for every possible
(typically using attributes or metadata) must be valid for every possible
representation of the pointer.

.. _globalvars:
Expand Down Expand Up @@ -1649,10 +1649,10 @@ Currently, only the following parameter attributes are defined:
- Both ``a`` and ``b`` are constants.
- The range is allowed to wrap.
- The range should not represent the full or empty set. That is, ``a!=b``.
This attribute may only be applied to parameters or return values with integer

This attribute may only be applied to parameters or return values with integer
or vector of integer types.

For vector-typed parameters, the range is applied element-wise.

.. _gc:
Expand Down Expand Up @@ -8699,7 +8699,10 @@ functions with the same priority is not defined.

If the third field is non-null, and points to a global variable
or function, the initializer function will only run if the associated
data from the current module is not discarded.
data from the current module is not discarded. An unqualified pointer is used
unconditionally to underline the ephemeral nature of this field - it is
essentially a lifetime hook meant for internal compiler usage, just like the
elements of the ``@llvm.used`` and ``@llvm.compiler.used`` arrays.
On ELF the referenced global variable or function must be in a comdat.

.. _llvmglobaldtors:
Expand All @@ -8720,7 +8723,10 @@ order of functions with the same priority is not defined.

If the third field is non-null, and points to a global variable
or function, the destructor function will only run if the associated
data from the current module is not discarded.
data from the current module is not discarded. An unqualified pointer is used
unconditionally to underline the ephemeral nature of this field - it is
essentially a lifetime hook meant for internal compiler usage, just like the
elements of the ``@llvm.used`` and ``@llvm.compiler.used`` arrays.
On ELF the referenced global variable or function must be in a comdat.

Instruction Reference
Expand Down Expand Up @@ -14254,7 +14260,7 @@ Arguments:
""""""""""
The first 4 arguments are similar to ``llvm.instrprof.increment``. The indexing
is specific to callsites, meaning callsites are indexed from 0, independent from
the indexes used by the other intrinsics (such as
the indexes used by the other intrinsics (such as
``llvm.instrprof.increment[.step]``).

The last argument is the called value of the callsite this intrinsic precedes.
Expand All @@ -14268,7 +14274,7 @@ a buffer LLVM can use to perform counter increments (i.e. the lowering of
``llvm.instrprof.increment[.step]``. The address range following the counter
buffer, ``<num-counters>`` x ``sizeof(ptr)`` - sized, is expected to contain
pointers to contexts of functions called from this function ("subcontexts").
LLVM does not dereference into that memory region, just calculates GEPs.
LLVM does not dereference into that memory region, just calculates GEPs.

The lowering of ``llvm.instrprof.callsite`` consists of:

Expand Down Expand Up @@ -14888,8 +14894,8 @@ integer bit width or any vector of integer elements.
Overview:
"""""""""

Return ``-1`` if ``%a`` is signed less than ``%b``, ``0`` if they are equal, and
``1`` if ``%a`` is signed greater than ``%b``. Vector intrinsics operate on a per-element basis.
Return ``-1`` if ``%a`` is signed less than ``%b``, ``0`` if they are equal, and
``1`` if ``%a`` is signed greater than ``%b``. Vector intrinsics operate on a per-element basis.

Arguments:
""""""""""
Expand Down Expand Up @@ -14917,8 +14923,8 @@ integer bit width or any vector of integer elements.
Overview:
"""""""""

Return ``-1`` if ``%a`` is unsigned less than ``%b``, ``0`` if they are equal, and
``1`` if ``%a`` is unsigned greater than ``%b``. Vector intrinsics operate on a per-element basis.
Return ``-1`` if ``%a`` is unsigned less than ``%b``, ``0`` if they are equal, and
``1`` if ``%a`` is unsigned greater than ``%b``. Vector intrinsics operate on a per-element basis.

Arguments:
""""""""""
Expand Down Expand Up @@ -20980,9 +20986,9 @@ Semantics:
""""""""""

The '``llvm.vp.minimum``' intrinsic performs floating-point minimum (:ref:`minimum <i_minimum>`)
of the first and second vector operand on each enabled lane, the result being
of the first and second vector operand on each enabled lane, the result being
NaN if either operand is a NaN. -0.0 is considered to be less than +0.0 for this
intrinsic. The result on disabled lanes is a :ref:`poison value <poisonvalues>`.
intrinsic. The result on disabled lanes is a :ref:`poison value <poisonvalues>`.
The operation is performed in the default floating-point environment.

Examples:
Expand Down Expand Up @@ -21030,9 +21036,9 @@ Semantics:
""""""""""

The '``llvm.vp.maximum``' intrinsic performs floating-point maximum (:ref:`maximum <i_maximum>`)
of the first and second vector operand on each enabled lane, the result being
of the first and second vector operand on each enabled lane, the result being
NaN if either operand is a NaN. -0.0 is considered to be less than +0.0 for this
intrinsic. The result on disabled lanes is a :ref:`poison value <poisonvalues>`.
intrinsic. The result on disabled lanes is a :ref:`poison value <poisonvalues>`.
The operation is performed in the default floating-point environment.

Examples:
Expand Down Expand Up @@ -28309,7 +28315,7 @@ Semantics:
""""""""""

The intrinsic ``@llvm.allow.ubsan.check()`` returns either ``true`` or
``false``, depending on compiler options.
``false``, depending on compiler options.

For each evaluation of a call to this intrinsic, the program must be valid and
correct both if it returns ``true`` and if it returns ``false``.
Expand Down Expand Up @@ -28368,13 +28374,13 @@ Semantics:
""""""""""

The intrinsic ``@llvm.allow.runtime.check()`` returns either ``true`` or
``false``, depending on compiler options.
``false``, depending on compiler options.

For each evaluation of a call to this intrinsic, the program must be valid and
correct both if it returns ``true`` and if it returns ``false``.

When used in a branch condition, it allows us to choose between
two alternative correct solutions for the same problem.
two alternative correct solutions for the same problem.

If the intrinsic is evaluated as ``true``, program should execute a guarded
check. If the intrinsic is evaluated as ``false``, the program should avoid any
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Transforms/Utils/ModuleUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
int Priority, Constant *Data) {
IRBuilder<> IRB(M.getContext());
FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
// The pointer to associated data MUST be emitted as an unqualified ptr, see
// the comment in CodeGenModule::EmitCtorList().
PointerType *AssocDataPtrTy = PointerType::getUnqual(M.getContext());

// Get the current set of static global constructors and add the new ctor
// to the list.
Expand All @@ -47,15 +50,15 @@ static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
} else {
EltTy = StructType::get(IRB.getInt32Ty(),
PointerType::get(FnTy, F->getAddressSpace()),
IRB.getPtrTy());
AssocDataPtrTy);
}

// Build a 3 field global_ctor entry. We don't take a comdat key.
Constant *CSVals[3];
CSVals[0] = IRB.getInt32(Priority);
CSVals[1] = F;
CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getPtrTy())
: Constant::getNullValue(IRB.getPtrTy());
CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, AssocDataPtrTy)
: Constant::getNullValue(AssocDataPtrTy);
Constant *RuntimeCtorInit =
ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements()));

Expand Down Expand Up @@ -437,12 +440,9 @@ bool llvm::lowerGlobalIFuncUsersAsGlobalCtor(

InitBuilder.CreateRetVoid();

PointerType *ConstantDataTy = PointerType::get(Ctx, 0);

// TODO: Is this the right priority? Probably should be before any other
// constructors?
const int Priority = 10;
appendToGlobalCtors(M, NewCtor, Priority,
ConstantPointerNull::get(ConstantDataTy));
appendToGlobalCtors(M, NewCtor, Priority, nullptr);
return UnhandledUsers;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ define void @existing_ctor() addrspace(1) {
; CHECK-FINAL: [[TABLE:@[0-9]+]] = internal addrspace(2) global [6 x ptr addrspace(1)] poison, align 8

; CHECK-FINAL: @llvm.global_ctors = appending addrspace(2) global [2 x { i32, ptr addrspace(1), ptr }] [{ i32, ptr addrspace(1), ptr } { i32 0, ptr addrspace(1) @existing_ctor, ptr null }, { i32, ptr addrspace(1), ptr } { i32 10, ptr addrspace(1) [[TABLE_CTOR:@[0-9]+]], ptr null }]
@llvm.global_ctors = appending global [1 x { i32, ptr addrspace(1), ptr }] [{ i32, ptr addrspace(1), ptr } { i32 0, ptr addrspace(1) @existing_ctor, ptr null }]
@llvm.global_ctors = appending addrspace(2) global [1 x { i32, ptr addrspace(1), ptr }] [{ i32, ptr addrspace(1), ptr } { i32 0, ptr addrspace(1) @existing_ctor, ptr null }]



Expand Down