diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2370,6 +2370,14 @@
program memory space defaults to the default address space of 0,
which corresponds to a Von Neumann architecture that has code
and data in the same space.
+``G
``
+ Specifies the address space to be used by default when creating global
+ variables. If omitted, the globals address space defaults to the default
+ address space 0.
+ Note: variable declarations without an address space are always created in
+ 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``
Specifies the address space of objects created by '``alloca``'.
Defaults to the default address space of 0.
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
@@ -123,6 +123,7 @@
unsigned AllocaAddrSpace;
MaybeAlign StackNaturalAlign;
unsigned ProgramAddrSpace;
+ unsigned DefaultGlobalsAddrSpace;
MaybeAlign FunctionPtrAlign;
FunctionPtrAlignType TheFunctionPtrAlignType;
@@ -219,6 +220,7 @@
FunctionPtrAlign = DL.FunctionPtrAlign;
TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType;
ProgramAddrSpace = DL.ProgramAddrSpace;
+ DefaultGlobalsAddrSpace = DL.DefaultGlobalsAddrSpace;
ManglingMode = DL.ManglingMode;
LegalIntWidths = DL.LegalIntWidths;
Alignments = DL.Alignments;
@@ -295,6 +297,9 @@
}
unsigned getProgramAddressSpace() const { return ProgramAddrSpace; }
+ unsigned getDefaultGlobalsAddressSpace() const {
+ return DefaultGlobalsAddrSpace;
+ }
bool hasMicrosoftFastStdCallMangling() const {
return ManglingMode == MM_WinCOFFX86;
diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h
--- a/llvm/include/llvm/IR/GlobalVariable.h
+++ b/llvm/include/llvm/IR/GlobalVariable.h
@@ -56,10 +56,11 @@
bool isExternallyInitialized = false);
/// GlobalVariable ctor - This creates a global and inserts it before the
/// specified other global.
- GlobalVariable(Module &M, Type *Ty, bool isConstant,
- LinkageTypes Linkage, Constant *Initializer,
- const Twine &Name = "", GlobalVariable *InsertBefore = nullptr,
- ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0,
+ GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage,
+ Constant *Initializer, const Twine &Name = "",
+ GlobalVariable *InsertBefore = nullptr,
+ ThreadLocalMode = NotThreadLocal,
+ Optional AddressSpace = None,
bool isExternallyInitialized = false);
GlobalVariable(const GlobalVariable &) = delete;
GlobalVariable &operator=(const GlobalVariable &) = delete;
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
@@ -182,6 +182,7 @@
AllocaAddrSpace = 0;
StackNaturalAlign.reset();
ProgramAddrSpace = 0;
+ DefaultGlobalsAddrSpace = 0;
FunctionPtrAlign.reset();
TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
ManglingMode = MM_None;
@@ -479,6 +480,11 @@
return Err;
break;
}
+ case 'G': { // Default address space for global variables.
+ if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace))
+ return Err;
+ break;
+ }
case 'm':
if (!Tok.empty())
return reportError("Unexpected trailing characters after mangling "
@@ -530,6 +536,7 @@
AllocaAddrSpace == Other.AllocaAddrSpace &&
StackNaturalAlign == Other.StackNaturalAlign &&
ProgramAddrSpace == Other.ProgramAddrSpace &&
+ DefaultGlobalsAddrSpace == Other.DefaultGlobalsAddrSpace &&
FunctionPtrAlign == Other.FunctionPtrAlign &&
TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType &&
ManglingMode == Other.ManglingMode &&
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -352,11 +352,15 @@
GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant,
LinkageTypes Link, Constant *InitVal,
const Twine &Name, GlobalVariable *Before,
- ThreadLocalMode TLMode, unsigned AddressSpace,
+ ThreadLocalMode TLMode,
+ Optional AddressSpace,
bool isExternallyInitialized)
: GlobalObject(Ty, Value::GlobalVariableVal,
OperandTraits::op_begin(this),
- InitVal != nullptr, Link, Name, AddressSpace),
+ InitVal != nullptr, Link, Name,
+ AddressSpace
+ ? *AddressSpace
+ : M.getDataLayout().getDefaultGlobalsAddressSpace()),
isConstantGlobal(constant),
isExternallyInitializedConstant(isExternallyInitialized) {
assert(!Ty->isFunctionTy() && PointerType::isValidElementType(Ty) &&
diff --git a/llvm/test/Assembler/invalid-datalayout-globals-addrspace.ll b/llvm/test/Assembler/invalid-datalayout-globals-addrspace.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Assembler/invalid-datalayout-globals-addrspace.ll
@@ -0,0 +1,4 @@
+; RUN: not --crash llvm-as < %s 2>&1 | FileCheck %s
+
+; CHECK: Invalid address space, must be a 24-bit integer
+target datalayout = "G16777216"
diff --git a/llvm/unittests/IR/DataLayoutTest.cpp b/llvm/unittests/IR/DataLayoutTest.cpp
--- a/llvm/unittests/IR/DataLayoutTest.cpp
+++ b/llvm/unittests/IR/DataLayoutTest.cpp
@@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "gtest/gtest.h"
@@ -56,4 +58,35 @@
DL.getValueOrABITypeAlignment(MaybeAlign(), FourByteAlignType));
}
-} // anonymous namespace
+TEST(DataLayoutTest, GlobalsAddressSpace) {
+ // When not explicitly defined the globals address space should be zero:
+ EXPECT_EQ(DataLayout("").getDefaultGlobalsAddressSpace(), 0u);
+ EXPECT_EQ(DataLayout("P1-A2").getDefaultGlobalsAddressSpace(), 0u);
+ EXPECT_EQ(DataLayout("G2").getDefaultGlobalsAddressSpace(), 2u);
+ // Check that creating a GlobalVariable without an explicit address space
+ // in a module with a default globals address space respects that default:
+ LLVMContext Context;
+ std::unique_ptr M(new Module("MyModule", Context));
+ // Default is globals in address space zero:
+ auto *Int32 = Type::getInt32Ty(Context);
+ auto *DefaultGlobal1 = new GlobalVariable(
+ *M, Int32, false, GlobalValue::ExternalLinkage, nullptr);
+ EXPECT_EQ(DefaultGlobal1->getAddressSpace(), 0u);
+ auto *ExplicitGlobal1 = new GlobalVariable(
+ *M, Int32, false, GlobalValue::ExternalLinkage, nullptr, "", nullptr,
+ GlobalValue::NotThreadLocal, 123);
+ EXPECT_EQ(ExplicitGlobal1->getAddressSpace(), 123u);
+
+ // When using a datalayout with the global address space set to 200, global
+ // variables should default to 200
+ M->setDataLayout("G200");
+ auto *DefaultGlobal2 = new GlobalVariable(
+ *M, Int32, false, GlobalValue::ExternalLinkage, nullptr);
+ EXPECT_EQ(DefaultGlobal2->getAddressSpace(), 200u);
+ auto *ExplicitGlobal2 = new GlobalVariable(
+ *M, Int32, false, GlobalValue::ExternalLinkage, nullptr, "", nullptr,
+ GlobalValue::NotThreadLocal, 123);
+ EXPECT_EQ(ExplicitGlobal2->getAddressSpace(), 123u);
+}
+
+} // anonymous namespace