diff options
author | Christopher Lamb <christopher.lamb@gmail.com> | 2007-12-11 08:59:05 +0000 |
---|---|---|
committer | Christopher Lamb <christopher.lamb@gmail.com> | 2007-12-11 08:59:05 +0000 |
commit | 44d62f61323cef4a7f88fb4a6de233cdcafebe8a (patch) | |
tree | 6a39f01b605f8fe68fa2e0c69f4e4c903c558967 /lib | |
parent | b93bdf6e2e9f024f504f10c4f01cc54bf1a7ca80 (diff) | |
download | external_llvm-44d62f61323cef4a7f88fb4a6de233cdcafebe8a.zip external_llvm-44d62f61323cef4a7f88fb4a6de233cdcafebe8a.tar.gz external_llvm-44d62f61323cef4a7f88fb4a6de233cdcafebe8a.tar.bz2 |
Implement address space attribute for LLVM pointer types. Address spaces are
regions of memory that have a target specific relationship, as described in the
Embedded C Technical Report.
This also implements the 2007-12-11-AddressSpaces test,
which demonstrates how address space attributes can be used in LLVM IR.
In addition, this patch changes the bitcode signature for stores (in a backwards
compatible manner), such that the pointer type, rather than the pointee type, is
encoded. This permits type information in the pointer (e.g. address space) to be
preserved for stores.
LangRef updates are forthcoming.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44858 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 31 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 28 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 16 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 11 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 3 | ||||
-rw-r--r-- | lib/VMCore/Globals.cpp | 10 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 6 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 31 |
9 files changed, 103 insertions, 34 deletions
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index ef8d27c..7505294 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 57b6f81..cd3a7ed 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 fd3ec9e..72756ef 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 612d893..c58d23a 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 008c1da..e35b14f 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 49c27b8..964d888 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 eb0df60..0155915 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 0df0466..5207ea5 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 1e58477..62de6f4 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"; |