1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Make the LLParser accept call instructions of variables in the program AS

Summary:
Since r325479 the DataLayout includes a program address space. However, it
is not possible to use `call %foo` if foo is a `i8(...) addrspace(200)` and
the DataLayout specifies address space 200 as the address space for functions.
With this change the IR parser will still accept variables in the program
address space as well as address space 0 for call and invoke functions.

Reviewers: pcc, arsenm, bjope, dylanmckay, theraven

Reviewed By: dylanmckay

Subscribers: wdng, llvm-commits

Differential Revision: https://reviews.llvm.org/D43645

llvm-svn: 326188
This commit is contained in:
Alexander Richardson 2018-02-27 11:15:11 +00:00
parent 16bd68e6b0
commit 499baa0abb
5 changed files with 80 additions and 19 deletions

View File

@ -2612,11 +2612,24 @@ bool LLParser::PerFunctionState::FinishFunction() {
return false; 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 /// GetVal - Get a value with the specified name or ID, creating a
/// forward reference record if needed. This can return null if the value /// forward reference record if needed. This can return null if the value
/// exists but does not have the right type. /// exists but does not have the right type.
Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty, 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. // Look this name up in the normal function symbol table.
Value *Val = F.getValueSymbolTable()->lookup(Name); 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 we have the value in the symbol table or fwd-ref table, return it.
if (Val) { if (Val) {
if (Val->getType() == Ty) return Val; if (isValidVariableType(P.M, Ty, Val, IsCall))
return Val;
if (Ty->isLabelTy()) if (Ty->isLabelTy())
P.Error(Loc, "'%" + Name + "' is not a basic block"); P.Error(Loc, "'%" + Name + "' is not a basic block");
else else
@ -2657,7 +2671,8 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
return FwdVal; 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. // Look this name up in the normal function symbol table.
Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; 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 we have the value in the symbol table or fwd-ref table, return it.
if (Val) { if (Val) {
if (Val->getType() == Ty) return Val; if (isValidVariableType(P.M, Ty, Val, IsCall))
return Val;
if (Ty->isLabelTy()) if (Ty->isLabelTy())
P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block"); P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block");
else else
@ -2762,13 +2778,13 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
/// forward reference record if needed. /// forward reference record if needed.
BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name,
LocTy Loc) { LocTy Loc) {
return dyn_cast_or_null<BasicBlock>(GetVal(Name, return dyn_cast_or_null<BasicBlock>(
Type::getLabelTy(F.getContext()), Loc)); GetVal(Name, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false));
} }
BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) {
return dyn_cast_or_null<BasicBlock>(GetVal(ID, return dyn_cast_or_null<BasicBlock>(
Type::getLabelTy(F.getContext()), Loc)); GetVal(ID, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false));
} }
/// DefineBB - Define the specified basic block, which is either named or /// DefineBB - Define the specified basic block, which is either named or
@ -3387,7 +3403,7 @@ bool LLParser::ParseGlobalValue(Type *Ty, Constant *&C) {
ValID ID; ValID ID;
Value *V = nullptr; Value *V = nullptr;
bool Parsed = ParseValID(ID) || bool Parsed = ParseValID(ID) ||
ConvertValIDToValue(Ty, ID, V, nullptr); ConvertValIDToValue(Ty, ID, V, nullptr, /*IsCall=*/false);
if (V && !(C = dyn_cast<Constant>(V))) if (V && !(C = dyn_cast<Constant>(V)))
return Error(ID.Loc, "global values must be constants"); return Error(ID.Loc, "global values must be constants");
return Parsed; return Parsed;
@ -4729,18 +4745,18 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
PerFunctionState *PFS) { PerFunctionState *PFS, bool IsCall) {
if (Ty->isFunctionTy()) if (Ty->isFunctionTy())
return Error(ID.Loc, "functions are not values, refer to them as pointers"); return Error(ID.Loc, "functions are not values, refer to them as pointers");
switch (ID.Kind) { switch (ID.Kind) {
case ValID::t_LocalID: case ValID::t_LocalID:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); 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; return V == nullptr;
case ValID::t_LocalName: case ValID::t_LocalName:
if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); 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; return V == nullptr;
case ValID::t_InlineAsm: { case ValID::t_InlineAsm: {
if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) 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_ConstantStruct:
case ValID::t_PackedConstantStruct: { case ValID::t_PackedConstantStruct: {
Value *V; Value *V;
if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr)) if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr, /*IsCall=*/false))
return true; return true;
assert(isa<Constant>(V) && "Expected a constant value"); assert(isa<Constant>(V) && "Expected a constant value");
C = cast<Constant>(V); C = cast<Constant>(V);
@ -4873,7 +4889,8 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
V = nullptr; V = nullptr;
ValID ID; 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) { bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
@ -5626,7 +5643,8 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
// Look up the callee. // Look up the callee.
Value *Callee; Value *Callee;
if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS,
/*IsCall=*/true))
return true; return true;
// Set up the Attribute for the function. // Set up the Attribute for the function.
@ -6217,7 +6235,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
// Look up the callee. // Look up the callee.
Value *Callee; Value *Callee;
if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS)) if (ConvertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS,
/*IsCall=*/true))
return true; return true;
// Set up the Attribute for the function. // Set up the Attribute for the function.

View File

@ -358,8 +358,8 @@ namespace llvm {
/// GetVal - Get a value with the specified name or ID, creating a /// GetVal - Get a value with the specified name or ID, creating a
/// forward reference record if needed. This can return null if the value /// forward reference record if needed. This can return null if the value
/// exists but does not have the right type. /// exists but does not have the right type.
Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc); Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc, bool IsCall);
Value *GetVal(unsigned ID, Type *Ty, LocTy Loc); Value *GetVal(unsigned ID, Type *Ty, LocTy Loc, bool IsCall);
/// SetInstName - After an instruction is parsed and inserted into its /// SetInstName - After an instruction is parsed and inserted into its
/// basic block, this installs its name. /// basic block, this installs its name.
@ -381,7 +381,7 @@ namespace llvm {
}; };
bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
PerFunctionState *PFS); PerFunctionState *PFS, bool IsCall);
bool parseConstantValue(Type *Ty, Constant *&C); bool parseConstantValue(Type *Ty, Constant *&C);
bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS); bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS);

View File

@ -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
}

View File

@ -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(...)

View File

@ -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(...)