summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp51
-rw-r--r--llvm/lib/AsmParser/LLParser.h6
-rw-r--r--llvm/test/Assembler/call-nonzero-program-addrspace-2.ll11
-rw-r--r--llvm/test/Assembler/call-nonzero-program-addrspace.ll13
-rw-r--r--llvm/test/Assembler/invoke-nonzero-program-addrspace.ll18
5 files changed, 80 insertions, 19 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 42c579878c1..29e6b07a76b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2612,11 +2612,24 @@ bool LLParser::PerFunctionState::FinishFunction() {
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<PointerType>(Ty)) {
+ Type *TyInProgAS = cast<PointerType>(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 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
// 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 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
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 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) {
// 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 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
/// forward reference record if needed.
BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name,
LocTy Loc) {
- return dyn_cast_or_null<BasicBlock>(GetVal(Name,
- Type::getLabelTy(F.getContext()), Loc));
+ return dyn_cast_or_null<BasicBlock>(
+ GetVal(Name, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false));
}
BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) {
- return dyn_cast_or_null<BasicBlock>(GetVal(ID,
- Type::getLabelTy(F.getContext()), Loc));
+ return dyn_cast_or_null<BasicBlock>(
+ GetVal(ID, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false));
}
/// DefineBB - Define the specified basic block, which is either named or
@@ -3387,7 +3403,7 @@ bool LLParser::ParseGlobalValue(Type *Ty, Constant *&C) {
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<Constant>(V)))
return Error(ID.Loc, "global values must be constants");
return Parsed;
@@ -4729,18 +4745,18 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
//===----------------------------------------------------------------------===//
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 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
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<Constant>(V) && "Expected a constant value");
C = cast<Constant>(V);
@@ -4873,7 +4889,8 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
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 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
// 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 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
// 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.
diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index a3252ff5f19..79428d4b703 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -358,8 +358,8 @@ namespace llvm {
/// 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 @@ namespace llvm {
};
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);
diff --git a/llvm/test/Assembler/call-nonzero-program-addrspace-2.ll b/llvm/test/Assembler/call-nonzero-program-addrspace-2.ll
new file mode 100644
index 00000000000..ed8546c61c8
--- /dev/null
+++ b/llvm/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
+}
diff --git a/llvm/test/Assembler/call-nonzero-program-addrspace.ll b/llvm/test/Assembler/call-nonzero-program-addrspace.ll
new file mode 100644
index 00000000000..1d1a224212d
--- /dev/null
+++ b/llvm/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(...)
diff --git a/llvm/test/Assembler/invoke-nonzero-program-addrspace.ll b/llvm/test/Assembler/invoke-nonzero-program-addrspace.ll
new file mode 100644
index 00000000000..443884590d6
--- /dev/null
+++ b/llvm/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(...)
OpenPOWER on IntegriCloud