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 = !{}