Index: llvm/trunk/lib/AsmParser/LLParser.h =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.h +++ llvm/trunk/lib/AsmParser/LLParser.h @@ -358,8 +358,8 @@ /// GetVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. - Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc); - Value *GetVal(unsigned ID, Type *Ty, LocTy Loc); + Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc, bool IsCall); + Value *GetVal(unsigned ID, Type *Ty, LocTy Loc, bool IsCall); /// SetInstName - After an instruction is parsed and inserted into its /// basic block, this installs its name. @@ -381,7 +381,7 @@ }; bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, - PerFunctionState *PFS); + PerFunctionState *PFS, bool IsCall); bool parseConstantValue(Type *Ty, Constant *&C); bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS); Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -2612,11 +2612,24 @@ return false; } +static bool isValidVariableType(Module *M, Type *Ty, Value *Val, bool IsCall) { + if (Val->getType() == Ty) + return true; + // For calls we also accept variables in the program address space + if (IsCall && isa(Ty)) { + Type *TyInProgAS = cast(Ty)->getElementType()->getPointerTo( + M->getDataLayout().getProgramAddressSpace()); + if (Val->getType() == TyInProgAS) + return true; + } + return false; +} + /// GetVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty, - LocTy Loc) { + LocTy Loc, bool IsCall) { // Look this name up in the normal function symbol table. Value *Val = F.getValueSymbolTable()->lookup(Name); @@ -2630,7 +2643,8 @@ // If we have the value in the symbol table or fwd-ref table, return it. if (Val) { - if (Val->getType() == Ty) return Val; + if (isValidVariableType(P.M, Ty, Val, IsCall)) + return Val; if (Ty->isLabelTy()) P.Error(Loc, "'%" + Name + "' is not a basic block"); else @@ -2657,7 +2671,8 @@ return FwdVal; } -Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) { +Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc, + bool IsCall) { // Look this name up in the normal function symbol table. Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; @@ -2671,7 +2686,8 @@ // If we have the value in the symbol table or fwd-ref table, return it. if (Val) { - if (Val->getType() == Ty) return Val; + if (isValidVariableType(P.M, Ty, Val, IsCall)) + return Val; if (Ty->isLabelTy()) P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block"); else @@ -2762,13 +2778,13 @@ /// forward reference record if needed. BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, LocTy Loc) { - return dyn_cast_or_null(GetVal(Name, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null( + GetVal(Name, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false)); } BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { - return dyn_cast_or_null(GetVal(ID, - Type::getLabelTy(F.getContext()), Loc)); + return dyn_cast_or_null( + GetVal(ID, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false)); } /// DefineBB - Define the specified basic block, which is either named or @@ -3387,7 +3403,7 @@ ValID ID; Value *V = nullptr; bool Parsed = ParseValID(ID) || - ConvertValIDToValue(Ty, ID, V, nullptr); + ConvertValIDToValue(Ty, ID, V, nullptr, /*IsCall=*/false); if (V && !(C = dyn_cast(V))) return Error(ID.Loc, "global values must be constants"); return Parsed; @@ -4729,18 +4745,18 @@ //===----------------------------------------------------------------------===// bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, - PerFunctionState *PFS) { + PerFunctionState *PFS, bool IsCall) { if (Ty->isFunctionTy()) return Error(ID.Loc, "functions are not values, refer to them as pointers"); switch (ID.Kind) { case ValID::t_LocalID: if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); - V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc); + V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc, IsCall); return V == nullptr; case ValID::t_LocalName: if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); - V = PFS->GetVal(ID.StrVal, Ty, ID.Loc); + V = PFS->GetVal(ID.StrVal, Ty, ID.Loc, IsCall); return V == nullptr; case ValID::t_InlineAsm: { if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) @@ -4856,7 +4872,7 @@ case ValID::t_ConstantStruct: case ValID::t_PackedConstantStruct: { Value *V; - if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr)) + if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr, /*IsCall=*/false)) return true; assert(isa(V) && "Expected a constant value"); C = cast(V); @@ -4873,7 +4889,8 @@ bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { V = nullptr; ValID ID; - return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS); + return ParseValID(ID, PFS) || + ConvertValIDToValue(Ty, ID, V, PFS, /*IsCall=*/false); } bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) { @@ -5626,7 +5643,8 @@ // Look up the callee. Value *Callee; - if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) + if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS, + /*IsCall=*/true)) return true; // Set up the Attribute for the function. @@ -6217,7 +6235,8 @@ // Look up the callee. Value *Callee; - if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) + if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS, + /*IsCall=*/true)) return true; // Set up the Attribute for the function. Index: llvm/trunk/test/Assembler/call-nonzero-program-addrspace-2.ll =================================================================== --- llvm/trunk/test/Assembler/call-nonzero-program-addrspace-2.ll +++ llvm/trunk/test/Assembler/call-nonzero-program-addrspace-2.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as %s -data-layout=P200 -o /dev/null +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; Check that numbered variables in a nonzero program address space 200 can be used in a call instruction + +define i8 @test_unnamed(i8(i32)*, i8(i32) addrspace(200)*) { + %first = call i8 %0(i32 0) ; this is fine + %second = call i8 %1(i32 0) ; this is also fine if it's the program AS + ; CHECK: call-nonzero-program-addrspace-2.ll:[[@LINE-1]]:21: error: '%1' defined with type 'i8 (i32) addrspace(200)*' + ret i8 0 +} Index: llvm/trunk/test/Assembler/call-nonzero-program-addrspace.ll =================================================================== --- llvm/trunk/test/Assembler/call-nonzero-program-addrspace.ll +++ llvm/trunk/test/Assembler/call-nonzero-program-addrspace.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as %s -data-layout=P200 -o /dev/null +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; Check that variables in a nonzero program address space 200 can be used in a call instruction + +define i8 @test(i8(i32)* %fnptr0, i8(i32) addrspace(200)* %fnptr200) { + %first = call i8 %fnptr0(i32 0) ; this is fine + %second = call i8 %fnptr200(i32 0) ; this is also fine if it's the program AS + ; CHECK: call-nonzero-program-addrspace.ll:[[@LINE-1]]:21: error: '%fnptr200' defined with type 'i8 (i32) addrspace(200)*' + ret i8 0 +} + +declare i32 @__gxx_personality_v0(...) Index: llvm/trunk/test/Assembler/invoke-nonzero-program-addrspace.ll =================================================================== --- llvm/trunk/test/Assembler/invoke-nonzero-program-addrspace.ll +++ llvm/trunk/test/Assembler/invoke-nonzero-program-addrspace.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as %s -data-layout=P200 -o /dev/null +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; Check that variables in a nonzero program address space 200 can be used in a invoke instruction + +define i8 @test_invoke(i8(i32)* %fnptr0, i8(i32) addrspace(200)* %fnptr200) personality i32 (...)* @__gxx_personality_v0 { + %first = invoke i8 %fnptr0(i32 0) to label %ok unwind label %lpad ; this is fine + %second = invoke i8 %fnptr200(i32 0) to label %ok unwind label %lpad ; this is also fine if it's the program AS + ; CHECK: invoke-nonzero-program-addrspace.ll:[[@LINE-1]]:23: error: '%fnptr200' defined with type 'i8 (i32) addrspace(200)*' +ok: + ret i8 0 +lpad: + %exn = landingpad {i8*, i32} + cleanup + unreachable +} + +declare i32 @__gxx_personality_v0(...)