aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h10
-rw-r--r--include/llvm/DerivedTypes.h9
-rw-r--r--include/llvm/GlobalVariable.h6
-rw-r--r--include/llvm/Instructions.h6
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/llvmAsmParser.y31
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp28
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp16
-rw-r--r--lib/VMCore/AsmWriter.cpp11
-rw-r--r--lib/VMCore/Constants.cpp3
-rw-r--r--lib/VMCore/Globals.cpp10
-rw-r--r--lib/VMCore/Instructions.cpp6
-rw-r--r--lib/VMCore/Type.cpp31
-rw-r--r--test/Assembler/2007-12-11-AddressSpaces.ll25
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp1
15 files changed, 151 insertions, 43 deletions
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 32311b26d9..8d95c872a9 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -46,7 +46,7 @@ namespace bitc {
MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N]
MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N]
- // GLOBALVAR: [type, isconst, initid,
+ // GLOBALVAR: [pointer type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal]
MODULE_CODE_GLOBALVAR = 7,
@@ -194,9 +194,13 @@ namespace bitc {
FUNC_CODE_INST_FREE = 18, // FREE: [opty, op]
FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align]
FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol]
- FUNC_CODE_INST_STORE = 21, // STORE: [ptrty,val,ptr, align, vol]
+ FUNC_CODE_INST_STORE = 21, // STORE: [valty,val,ptr, align, vol]
FUNC_CODE_INST_CALL = 22, // CALL: [attr, fnty, fnid, args...]
- FUNC_CODE_INST_VAARG = 23 // VAARG: [valistty, valist, instty]
+ FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty]
+ // This store code encodes the pointer type, rather than the value type
+ // this is so information only available in the pointer type (e.g. address
+ // spaces) is retained.
+ FUNC_CODE_INST_STORE2 = 24 // STORE: [ptrty,ptr,val, align, vol]
};
} // End bitc namespace
} // End llvm namespace
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index 12219c5354..d62cb3bcc9 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -363,12 +363,17 @@ public:
///
class PointerType : public SequentialType {
friend class TypeMap<PointerValType, PointerType>;
+ unsigned AddressSpace;
+
PointerType(const PointerType &); // Do not implement
const PointerType &operator=(const PointerType &); // Do not implement
- explicit PointerType(const Type *ElType);
+ explicit PointerType(const Type *ElType, unsigned AddrSpace);
public:
/// PointerType::get - This is the only way to construct a new pointer type.
- static PointerType *get(const Type *ElementType);
+ static PointerType *get(const Type *ElementType, unsigned AddressSpace = 0);
+
+ /// @brief Return the address space of the Pointer type.
+ inline unsigned getAddressSpace() const { return AddressSpace; }
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h
index 00d4acb66d..7e99ae04ba 100644
--- a/include/llvm/GlobalVariable.h
+++ b/include/llvm/GlobalVariable.h
@@ -50,12 +50,14 @@ public:
/// automatically inserted into the end of the specified modules global list.
GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage,
Constant *Initializer = 0, const std::string &Name = "",
- Module *Parent = 0, bool ThreadLocal = false);
+ Module *Parent = 0, bool ThreadLocal = false,
+ unsigned AddressSpace = 0);
/// GlobalVariable ctor - This creates a global and inserts it before the
/// specified other global.
GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage,
Constant *Initializer, const std::string &Name,
- GlobalVariable *InsertBefore, bool ThreadLocal = false);
+ GlobalVariable *InsertBefore, bool ThreadLocal = false,
+ unsigned AddressSpace = 0);
/// isDeclaration - Is this global variable lacking an initializer? If so,
/// the global variable is defined in some other translation unit, and is thus
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index bc5e0b4af9..3c8673e627 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -455,7 +455,8 @@ public:
Instruction *InsertBefore =0)
: Instruction(PointerType::get(
checkType(getIndexedType(Ptr->getType(),
- IdxBegin, IdxEnd, true))),
+ IdxBegin, IdxEnd, true)),
+ cast<PointerType>(Ptr->getType())->getAddressSpace()),
GetElementPtr, 0, 0, InsertBefore) {
init(Ptr, IdxBegin, IdxEnd, Name,
typename std::iterator_traits<InputIterator>::iterator_category());
@@ -465,7 +466,8 @@ public:
const std::string &Name, BasicBlock *InsertAtEnd)
: Instruction(PointerType::get(
checkType(getIndexedType(Ptr->getType(),
- IdxBegin, IdxEnd, true))),
+ IdxBegin, IdxEnd, true)),
+ cast<PointerType>(Ptr->getType())->getAddressSpace()),
GetElementPtr, 0, 0, InsertAtEnd) {
init(Ptr, IdxBegin, IdxEnd, Name,
typename std::iterator_traits<InputIterator>::iterator_category());
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index ef8d27c8a3..750529451a 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -463,6 +463,7 @@ int LLLexer::LexIdentifier() {
KEYWORD("datalayout", DATALAYOUT);
KEYWORD("volatile", VOLATILE);
KEYWORD("align", ALIGN);
+ KEYWORD("addrspace", ADDRSPACE);
KEYWORD("section", SECTION);
KEYWORD("alias", ALIAS);
KEYWORD("module", MODULE);
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 57b6f81d8f..cd3a7edb50 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -491,7 +491,8 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
if (const FunctionType *FTy = dyn_cast<FunctionType>(ElTy))
V = new Function(FTy, GlobalValue::ExternalLinkage);
else
- V = new GlobalVariable(ElTy, false, GlobalValue::ExternalLinkage);
+ V = new GlobalVariable(ElTy, false, GlobalValue::ExternalLinkage, 0, "",
+ (Module*)0, false, PTy->getAddressSpace());
break;
}
default:
@@ -722,13 +723,14 @@ ParseGlobalVariable(std::string *NameStr,
GlobalValue::LinkageTypes Linkage,
GlobalValue::VisibilityTypes Visibility,
bool isConstantGlobal, const Type *Ty,
- Constant *Initializer, bool IsThreadLocal) {
+ Constant *Initializer, bool IsThreadLocal,
+ unsigned AddressSpace = 0) {
if (isa<FunctionType>(Ty)) {
GenerateError("Cannot declare global vars of function type");
return 0;
}
- const PointerType *PTy = PointerType::get(Ty);
+ const PointerType *PTy = PointerType::get(Ty, AddressSpace);
std::string Name;
if (NameStr) {
@@ -780,7 +782,7 @@ ParseGlobalVariable(std::string *NameStr,
// Otherwise there is no existing GV to use, create one now.
GlobalVariable *GV =
new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name,
- CurModule.CurrentModule, IsThreadLocal);
+ CurModule.CurrentModule, IsThreadLocal, AddressSpace);
GV->setVisibility(Visibility);
InsertValue(GV, CurModule.Values);
return GV;
@@ -1054,7 +1056,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%token DECLARE DEFINE GLOBAL CONSTANT SECTION ALIAS VOLATILE THREAD_LOCAL
%token TO DOTDOTDOT NULL_TOK UNDEF INTERNAL LINKONCE WEAK APPENDING
%token DLLIMPORT DLLEXPORT EXTERN_WEAK
-%token OPAQUE EXTERNAL TARGET TRIPLE ALIGN
+%token OPAQUE EXTERNAL TARGET TRIPLE ALIGN ADDRSPACE
%token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT
%token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
%token DATALAYOUT
@@ -1268,6 +1270,7 @@ OptCAlign : /*empty*/ { $$ = 0; } |
};
+
SectionString : SECTION STRINGCONSTANT {
for (unsigned i = 0, e = $2->length(); i != e; ++i)
if ((*$2)[i] == '"' || (*$2)[i] == '\\')
@@ -1320,6 +1323,13 @@ Types
delete $1;
CHECK_FOR_ERROR
}
+ | Types ADDRSPACE '(' EUINT64VAL ')' '*' { // Pointer type?
+ if (*$1 == Type::LabelTy)
+ GEN_ERROR("Cannot form a pointer to a basic block");
+ $$ = new PATypeHolder(HandleUpRefs(PointerType::get(*$1, $4)));
+ delete $1;
+ CHECK_FOR_ERROR
+ }
| SymbolicValueRef { // Named types are also simple types...
const Type* tmp = getTypeVal($1);
CHECK_FOR_ERROR
@@ -2073,6 +2083,17 @@ Definition
} GlobalVarAttributes {
CurGV = 0;
}
+ | OptGlobalAssign GVVisibilityStyle ThreadLocal GlobalType ConstVal
+ ADDRSPACE '(' EUINT64VAL ')' {
+ /* "Externally Visible" Linkage with address space qualifier */
+ if ($5 == 0)
+ GEN_ERROR("Global value initializer is not a constant");
+ CurGV = ParseGlobalVariable($1, GlobalValue::ExternalLinkage,
+ $2, $4, $5->getType(), $5, $3, $8);
+ CHECK_FOR_ERROR
+ } GlobalVarAttributes {
+ CurGV = 0;
+ }
| OptGlobalAssign GVInternalLinkage GVVisibilityStyle ThreadLocal GlobalType
ConstVal {
if ($6 == 0)
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index fd3ec9e698..72756ef6cd 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -323,11 +323,16 @@ bool BitcodeReader::ParseTypeTable() {
ResultTy = IntegerType::get(Record[0]);
break;
- case bitc::TYPE_CODE_POINTER: // POINTER: [pointee type]
+ case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+ // [pointee type, address space]
if (Record.size() < 1)
return Error("Invalid POINTER type record");
- ResultTy = PointerType::get(getTypeByID(Record[0], true));
+ unsigned AddressSpace = 0;
+ if (Record.size() == 2)
+ AddressSpace = Record[1];
+ ResultTy = PointerType::get(getTypeByID(Record[0], true), AddressSpace);
break;
+ }
case bitc::TYPE_CODE_FUNCTION: {
// FIXME: attrid is dead, remove it in LLVM 3.0
// FUNCTION: [vararg, attrid, retty, paramty x N]
@@ -982,7 +987,7 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
CollectorTable.push_back(S);
break;
}
- // GLOBALVAR: [type, isconst, initid,
+ // GLOBALVAR: [pointer type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal]
case bitc::MODULE_CODE_GLOBALVAR: {
if (Record.size() < 6)
@@ -990,6 +995,7 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
const Type *Ty = getTypeByID(Record[0]);
if (!isa<PointerType>(Ty))
return Error("Global not a pointer type!");
+ unsigned AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
Ty = cast<PointerType>(Ty)->getElementType();
bool isConstant = Record[1];
@@ -1009,7 +1015,8 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
isThreadLocal = Record[7];
GlobalVariable *NewGV =
- new GlobalVariable(Ty, isConstant, Linkage, 0, "", TheModule);
+ new GlobalVariable(Ty, isConstant, Linkage, 0, "", TheModule,
+ isThreadLocal, AddressSpace);
NewGV->setAlignment(Alignment);
if (!Section.empty())
NewGV->setSection(Section);
@@ -1485,7 +1492,20 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1);
break;
}
+ case bitc::FUNC_CODE_INST_STORE2: { // STORE2:[ptrty, ptr, val, align, vol]
+ unsigned OpNum = 0;
+ Value *Val, *Ptr;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ getValue(Record, OpNum,
+ cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+ OpNum+2 != Record.size())
+ return Error("Invalid STORE record");
+
+ I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+ break;
+ }
case bitc::FUNC_CODE_INST_STORE: { // STORE:[val, valty, ptr, align, vol]
+ // FIXME: Legacy form of store instruction. Should be removed in LLVM 3.0.
unsigned OpNum = 0;
Value *Val, *Ptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Val) ||
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 612d89338b..c58d23ada2 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -197,10 +197,14 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
TypeVals.push_back(cast<IntegerType>(T)->getBitWidth());
break;
case Type::PointerTyID:
- // POINTER: [pointee type]
+ const PointerType *PTy = cast<PointerType>(T);
+ // POINTER: [pointee type] or [pointee type, address space]
Code = bitc::TYPE_CODE_POINTER;
- TypeVals.push_back(VE.getTypeID(cast<PointerType>(T)->getElementType()));
- AbbrevToUse = PtrAbbrev;
+ TypeVals.push_back(VE.getTypeID(PTy->getElementType()));
+ if (unsigned AddressSpace = PTy->getAddressSpace())
+ TypeVals.push_back(AddressSpace);
+ else
+ AbbrevToUse = PtrAbbrev;
break;
case Type::FunctionTyID: {
@@ -829,9 +833,9 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Vals.push_back(cast<LoadInst>(I).isVolatile());
break;
case Instruction::Store:
- Code = bitc::FUNC_CODE_INST_STORE;
- PushValueAndType(I.getOperand(0), InstID, Vals, VE); // val.
- Vals.push_back(VE.getValueID(I.getOperand(1))); // ptr.
+ Code = bitc::FUNC_CODE_INST_STORE2;
+ PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // val.
Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1);
Vals.push_back(cast<StoreInst>(I).isVolatile());
break;
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 008c1daee1..e35b14fbc1 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -334,11 +334,15 @@ static void calcTypeName(const Type *Ty,
Result += '>';
break;
}
- case Type::PointerTyID:
- calcTypeName(cast<PointerType>(Ty)->getElementType(),
+ case Type::PointerTyID: {
+ const PointerType *PTy = cast<PointerType>(Ty);
+ calcTypeName(PTy->getElementType(),
TypeStack, TypeNames, Result);
+ if (unsigned AddressSpace = PTy->getAddressSpace())
+ Result += " addrspace(" + utostr(AddressSpace) + ")";
Result += "*";
break;
+ }
case Type::ArrayTyID: {
const ArrayType *ATy = cast<ArrayType>(Ty);
Result += "[" + utostr(ATy->getNumElements()) + " x ";
@@ -951,6 +955,9 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
writeOperand(GV->getInitializer(), false);
}
+ if (unsigned AddressSpace = GV->getType()->getAddressSpace())
+ Out << " addrspace(" << AddressSpace << ") ";
+
if (GV->hasSection())
Out << ", section \"" << GV->getSection() << '"';
if (GV->getAlignment())
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 49c27b82cc..964d8880e8 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -1860,7 +1860,8 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
const Type *Ty =
GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx, true);
assert(Ty && "GEP indices invalid!");
- return getGetElementPtrTy(PointerType::get(Ty), C, Idxs, NumIdx);
+ unsigned As = cast<PointerType>(C->getType())->getAddressSpace();
+ return getGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx);
}
Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant* const *Idxs,
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
index eb0df60757..0155915146 100644
--- a/lib/VMCore/Globals.cpp
+++ b/lib/VMCore/Globals.cpp
@@ -85,8 +85,9 @@ void GlobalValue::destroyConstant() {
GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
Constant *InitVal, const std::string &Name,
- Module *ParentModule, bool ThreadLocal)
- : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal,
+ Module *ParentModule, bool ThreadLocal,
+ unsigned AddressSpace)
+ : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal,
&Initializer, InitVal != 0, Link, Name),
isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) {
if (InitVal) {
@@ -105,8 +106,9 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
Constant *InitVal, const std::string &Name,
- GlobalVariable *Before, bool ThreadLocal)
- : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal,
+ GlobalVariable *Before, bool ThreadLocal,
+ unsigned AddressSpace)
+ : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal,
&Initializer, InitVal != 0, Link, Name),
isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) {
if (InitVal) {
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 0df0466112..5207ea52f4 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -937,7 +937,8 @@ void GetElementPtrInst::init(Value *Ptr, Value *Idx) {
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, Instruction *InBe)
- : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx))),
+ : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
+ cast<PointerType>(Ptr->getType())->getAddressSpace()),
GetElementPtr, 0, 0, InBe) {
init(Ptr, Idx);
setName(Name);
@@ -945,7 +946,8 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, BasicBlock *IAE)
- : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx))),
+ : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
+ cast<PointerType>(Ptr->getType())->getAddressSpace()),
GetElementPtr, 0, 0, IAE) {
init(Ptr, Idx);
setName(Name);
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 1e58477042..62de6f4fa5 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -338,7 +338,10 @@ static std::string getTypeDescription(const Type *Ty,
}
case Type::PointerTyID: {
const PointerType *PTy = cast<PointerType>(Ty);
- Result = getTypeDescription(PTy->getElementType(), TypeStack) + " *";
+ Result = getTypeDescription(PTy->getElementType(), TypeStack);
+ if (unsigned AddressSpace = PTy->getAddressSpace())
+ Result += " addrspace(" + utostr(AddressSpace) + ")";
+ Result += " *";
break;
}
case Type::ArrayTyID: {
@@ -492,7 +495,9 @@ VectorType::VectorType(const Type *ElType, unsigned NumEl)
}
-PointerType::PointerType(const Type *E) : SequentialType(PointerTyID, E) {
+PointerType::PointerType(const Type *E, unsigned AddrSpace)
+ : SequentialType(PointerTyID, E) {
+ AddressSpace = AddrSpace;
// Calculate whether or not this type is abstract
setAbstract(E->isAbstract());
}
@@ -634,8 +639,9 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
const IntegerType *ITy2 = cast<IntegerType>(Ty2);
return ITy->getBitWidth() == ITy2->getBitWidth();
} else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- return TypesEqual(PTy->getElementType(),
- cast<PointerType>(Ty2)->getElementType(), EqTypes);
+ const PointerType *PTy2 = cast<PointerType>(Ty2);
+ return PTy->getAddressSpace() == PTy2->getAddressSpace() &&
+ TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes);
} else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
const StructType *STy2 = cast<StructType>(Ty2);
if (STy->getNumElements() != STy2->getNumElements()) return false;
@@ -756,6 +762,9 @@ static unsigned getSubElementHash(const Type *Ty) {
case Type::StructTyID:
HashVal ^= cast<StructType>(SubTy)->getNumElements();
break;
+ case Type::PointerTyID:
+ HashVal ^= cast<PointerType>(SubTy)->getAddressSpace();
+ break;
}
}
return HashVal ? HashVal : 1; // Do not return zero unless opaque subty.
@@ -1251,11 +1260,12 @@ StructType *StructType::get(const std::vector<const Type*> &ETypes,
namespace llvm {
class PointerValType {
const Type *ValTy;
+ unsigned AddressSpace;
public:
- PointerValType(const Type *val) : ValTy(val) {}
+ PointerValType(const Type *val, unsigned as) : ValTy(val), AddressSpace(as) {}
static PointerValType get(const PointerType *PT) {
- return PointerValType(PT->getElementType());
+ return PointerValType(PT->getElementType(), PT->getAddressSpace());
}
static unsigned hashTypeStructure(const PointerType *PT) {
@@ -1263,25 +1273,26 @@ public:
}
bool operator<(const PointerValType &MTV) const {
- return ValTy < MTV.ValTy;
+ if (AddressSpace < MTV.AddressSpace) return true;
+ return AddressSpace == MTV.AddressSpace && ValTy < MTV.ValTy;
}
};
}
static ManagedStatic<TypeMap<PointerValType, PointerType> > PointerTypes;
-PointerType *PointerType::get(const Type *ValueType) {
+PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) {
assert(ValueType && "Can't get a pointer to <null> type!");
assert(ValueType != Type::VoidTy &&
"Pointer to void is not valid, use sbyte* instead!");
assert(ValueType != Type::LabelTy && "Pointer to label is not valid!");
- PointerValType PVT(ValueType);
+ PointerValType PVT(ValueType, AddressSpace);
PointerType *PT = PointerTypes->get(PVT);
if (PT) return PT;
// Value not found. Derive a new type!
- PointerTypes->add(PVT, PT = new PointerType(ValueType));
+ PointerTypes->add(PVT, PT = new PointerType(ValueType, AddressSpace));
#ifdef DEBUG_MERGE_TYPES
DOUT << "Derived new type: " << *PT << "\n";
diff --git a/test/Assembler/2007-12-11-AddressSpaces.ll b/test/Assembler/2007-12-11-AddressSpaces.ll
new file mode 100644
index 0000000000..91f6d935ea
--- /dev/null
+++ b/test/Assembler/2007-12-11-AddressSpaces.ll
@@ -0,0 +1,25 @@
+; RUN: llvm-as < %s | llvm-dis |& grep {addrspace(33)} | count 7
+; RUN: llvm-as < %s | llvm-dis |& grep {addrspace(42)} | count 2
+; RUN: llvm-as < %s | llvm-dis |& grep {addrspace(66)} | count 2
+; RUN: llvm-as < %s | llvm-dis |& grep {addrspace(11)} | count 6
+; RUN: llvm-as < %s | llvm-dis |& grep {addrspace(22)} | count 5
+
+ %struct.mystruct = type { i32, i32 addrspace(33)*, i32, i32 addrspace(33)* }
+@input = global %struct.mystruct zeroinitializer addrspace(42) ; <%struct.mystruct addrspace(42)*> [#uses=1]
+@output = global %struct.mystruct zeroinitializer addrspace(66) ; <%struct.mystruct addrspace(66)*> [#uses=1]
+@y = global i32 addrspace(11)* addrspace(22)* null addrspace(33) ; <i32 addrspace(11)* addrspace(22)* addrspace(33)*> [#uses=1]
+
+define void @foo() {
+entry:
+ %tmp1 = load i32 addrspace(33)* addrspace(42)* getelementptr (%struct.mystruct addrspace(42)* @input, i32 0, i32 3), align 4 ; <i32 addrspace(33)*> [#uses=1]
+ store i32 addrspace(33)* %tmp1, i32 addrspace(33)* addrspace(66)* getelementptr (%struct.mystruct addrspace(66)* @output, i32 0, i32 1), align 4
+ ret void
+}
+
+define i32 addrspace(11)* @bar(i32 addrspace(11)* addrspace(22)* addrspace(33)* %x) {
+entry:
+ %tmp1 = load i32 addrspace(11)* addrspace(22)* addrspace(33)* @y, align 4 ; <i32 addrspace(11)* addrspace(22)*> [#uses=2]
+ store i32 addrspace(11)* addrspace(22)* %tmp1, i32 addrspace(11)* addrspace(22)* addrspace(33)* %x, align 4
+ %tmp5 = load i32 addrspace(11)* addrspace(22)* %tmp1, align 4 ; <i32 addrspace(11)*> [#uses=1]
+ ret i32 addrspace(11)* %tmp5
+}
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index b596fe3731..09156d68fd 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -197,6 +197,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID) {
case bitc::FUNC_CODE_INST_STORE: return "INST_STORE";
case bitc::FUNC_CODE_INST_CALL: return "INST_CALL";
case bitc::FUNC_CODE_INST_VAARG: return "INST_VAARG";
+ case bitc::FUNC_CODE_INST_STORE2: return "INST_STORE2";
}
case bitc::TYPE_SYMTAB_BLOCK_ID:
switch (CodeID) {