diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2449,9 +2449,17 @@ address space 0, this property only affects the default value to be used when creating globals without additional contextual information (e.g. in LLVM passes). -``A
`` +``A
:`` Specifies the address space of objects created by '``alloca``'. - Defaults to the default address space of 0. + Defaults to the default address space of 0. The ``:`` + suffix is optional; possible values are: + + * ``r``: Restricted ``alloca`` address spaces. The verifier will + check that ``alloca`` instructions are in the specified address + space. This is the default. + * ``u``: Unrestricted ``alloca`` address spaces. Though the default + address space for ``alloca`` is ``
``, the verifier will + allow ``alloca`` in other address spaces. ``p[n]::::`` This specifies the *size* of a pointer and its ```` and ````\erred alignments for address space ``n``. The fourth parameter @@ -9523,8 +9531,7 @@ The '``alloca``' instruction allocates memory on the stack frame of the currently executing function, to be automatically released when this -function returns to its caller. The object is always allocated in the -address space for allocas indicated in the datalayout. +function returns to its caller. Arguments: """""""""" @@ -9555,6 +9562,12 @@ pointer may not be unique. The order in which memory is allocated (ie., which way the stack grows) is not specified. +If not explicitly specified, the address space of the result defaults to +the designed alloca address space for the target. Note that most +targets require that the object be allocated in the address space for +allocas indicated in the datalayout. See :ref:`datalayout +string` for more on alloca address spaces. + If the returned pointer is used by :ref:`llvm.lifetime.start `, the returned object is initially dead. See :ref:`llvm.lifetime.start ` and diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -121,6 +121,7 @@ /// Defaults to false. bool BigEndian; + bool RestrictedAllocaAddrSpace; unsigned AllocaAddrSpace; MaybeAlign StackNaturalAlign; unsigned ProgramAddrSpace; @@ -211,6 +212,7 @@ clear(); StringRepresentation = DL.StringRepresentation; BigEndian = DL.isBigEndian(); + RestrictedAllocaAddrSpace = DL.restrictedAllocaAddrSpace(); AllocaAddrSpace = DL.AllocaAddrSpace; StackNaturalAlign = DL.StackNaturalAlign; FunctionPtrAlign = DL.FunctionPtrAlign; @@ -276,6 +278,7 @@ return *StackNaturalAlign; } + bool restrictedAllocaAddrSpace() const { return RestrictedAllocaAddrSpace; } unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } /// Returns the alignment of function pointers, which may or may not be diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -180,6 +180,7 @@ LayoutMap = nullptr; BigEndian = false; + RestrictedAllocaAddrSpace = true; AllocaAddrSpace = 0; StackNaturalAlign.reset(); ProgramAddrSpace = 0; @@ -479,6 +480,27 @@ case 'A': { // Default stack/alloca address space. if (Error Err = getAddrSpace(Tok, AllocaAddrSpace)) return Err; + if (!Rest.empty()) { + if (Error Err = split(Rest, ':', Split)) + return Err; + if (Tok.empty()) + return reportError("Unexpected trailing ':' in alloca addrspace " + "specifier in datalayout string"); + if (Tok.size() > 1) + return reportError("Unknown 'restricted' specifier in alloca " + "addrspace specifier in datalayout string"); + switch (Tok[0]) { + default: + return reportError("Unknown 'restricted' specifier in alloca " + "addrspace specifier in datalayout string"); + case 'r': + RestrictedAllocaAddrSpace = true; + break; + case 'u': + RestrictedAllocaAddrSpace = false; + break; + } + } break; } case 'G': { // Default address space for global variables. @@ -534,6 +556,7 @@ bool DataLayout::operator==(const DataLayout &Other) const { bool Ret = BigEndian == Other.BigEndian && + RestrictedAllocaAddrSpace == Other.RestrictedAllocaAddrSpace && AllocaAddrSpace == Other.AllocaAddrSpace && StackNaturalAlign == Other.StackNaturalAlign && ProgramAddrSpace == Other.ProgramAddrSpace && diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3802,10 +3802,9 @@ void Verifier::visitAllocaInst(AllocaInst &AI) { SmallPtrSet Visited; PointerType *PTy = AI.getType(); - // TODO: Relax this restriction? - Assert(PTy->getAddressSpace() == DL.getAllocaAddrSpace(), - "Allocation instruction pointer not in the stack address space!", - &AI); + Assert(PTy->getAddressSpace() == DL.getAllocaAddrSpace() || + !DL.restrictedAllocaAddrSpace(), + "Allocation instruction pointer not in the stack address space!", &AI); Assert(AI.getAllocatedType()->isSized(&Visited), "Cannot allocate unsized type", &AI); Assert(AI.getArraySize()->getType()->isIntegerTy(), diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-invalid-0.ll b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-0.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-0.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +target datalayout = "A1" + +define void @use_alloca() { +; CHECK: Allocation instruction pointer not in the stack address space! + %alloca_scalar_no_align = alloca i32, addrspace(2) + ret void +} diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-invalid-1.ll b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-1.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-1.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +target datalayout = "A1:r" + +define void @use_alloca() { +; CHECK: Allocation instruction pointer not in the stack address space! + %alloca_scalar_no_align = alloca i32, addrspace(2) + ret void +} diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-invalid-2.ll b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-2.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as < %s 2>&1 | FileCheck %s + +target datalayout = "" + +define void @use_alloca() { +; CHECK: Allocation instruction pointer not in the stack address space! + %alloca_scalar_no_align = alloca i32, addrspace(2) + ret void +} diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-valid.ll b/llvm/test/Verifier/alloca-alternate-addrspace-valid.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/alloca-alternate-addrspace-valid.ll @@ -0,0 +1,22 @@ +; RUN: llvm-as %s -o /dev/null + +; Should assemble without error. + +target datalayout = "A1:u" + +define void @use_alloca0() { + %alloca_scalar_no_align = alloca i32, addrspace(2) + ret void +} + +define void @use_alloca1() { + %alloca_scalar_no_align = alloca i32, align 4, addrspace(2) + ret void +} + +define void @use_alloca2() { + %alloca_scalar_no_align = alloca i32, align 4, addrspace(2), !foo !0 + ret void +} + +!0 = !{}