Index: src/PNaClTranslator.cpp |
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
index d7928659619a9fe6e8d6cf5f2f7395d9f9e73f57..ba9eabbd7265ad6b62e5e68ff5c813e3794b5f06 100644 |
--- a/src/PNaClTranslator.cpp |
+++ b/src/PNaClTranslator.cpp |
@@ -1598,7 +1598,7 @@ private: |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
StrBuf << InstructionName << " address not " << PtrType |
- << ". Found: " << *Op; |
+ << ". Found: " << Op->getType(); |
Error(StrBuf.str()); |
return false; |
} |
@@ -2048,6 +2048,24 @@ private: |
return LocalOperands.front(); |
return Context->getGlobalConstantByID(0); |
} |
+ |
+ void verifyCallArgTypeMatches(Ice::FunctionDeclaration *Fcn, |
+ Ice::SizeT Index, Ice::Type ArgType, |
+ Ice::Type ParamType) { |
+ if (ArgType != ParamType) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Argument " << (Index + 1) << " of " << printName(Fcn) |
+ << " expects " << ParamType << ". Found: " << ArgType; |
+ Error(StrBuf.str()); |
+ } |
+ } |
+ |
+ const Ice::IceString printName(Ice::FunctionDeclaration *Fcn) { |
+ if (Fcn) |
+ return Fcn->getName(); |
+ return "function"; |
+ } |
}; |
void FunctionParser::ExitBlock() { |
@@ -2660,46 +2678,116 @@ void FunctionParser::ProcessRecord() { |
ParamsStartIndex = 3; |
} |
- // Extract out the called function and its return type. |
uint32_t CalleeIndex = convertRelativeToAbsIndex(Values[1], BaseIndex); |
Ice::Operand *Callee = getOperand(CalleeIndex); |
+ |
+ // Pull out signature/return type of call (if possible). |
+ Ice::FunctionDeclaration *Fcn = nullptr; |
const Ice::FuncSigType *Signature = nullptr; |
Ice::Type ReturnType = Ice::IceType_void; |
const Ice::Intrinsics::FullIntrinsicInfo *IntrinsicInfo = nullptr; |
- // Name of function if a direct call/intrinsic. Null otherwise. |
- Ice::FunctionDeclaration *Fcn = nullptr; |
if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) { |
Fcn = Context->getFunctionByID(CalleeIndex); |
Signature = &Fcn->getSignature(); |
ReturnType = Signature->getReturnType(); |
+ Ice::SizeT NumParams = Values.size() - ParamsStartIndex; |
+ if (NumParams != Signature->getNumArgs()) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Call to " << printName(Fcn) << " has " << NumParams |
+ << " parameters. Signature expects: " << Signature->getNumArgs(); |
+ Error(StrBuf.str()); |
+ if (ReturnType != Ice::IceType_void) |
+ setNextLocalInstIndex(nullptr); |
+ return; |
+ } |
// Check if this direct call is to an Intrinsic (starts with "llvm.") |
bool BadIntrinsic; |
- const Ice::IceString &Name = Fcn->getName(); |
IntrinsicInfo = getTranslator().getContext()->getIntrinsicsInfo().find( |
- Name, BadIntrinsic); |
+ Fcn->getName(), BadIntrinsic); |
if (BadIntrinsic) { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Invalid PNaCl intrinsic call to " << Name; |
+ StrBuf << "Invalid PNaCl intrinsic call to " << Fcn->getName(); |
+ Error(StrBuf.str()); |
+ IntrinsicInfo = nullptr; |
+ } |
+ if (IntrinsicInfo && IntrinsicInfo->getNumArgs() != NumParams) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Call to " << printName(Fcn) << " has " << NumParams |
+ << " parameters. Intrinsic expects: " << Signature->getNumArgs(); |
Error(StrBuf.str()); |
if (ReturnType != Ice::IceType_void) |
- appendErrorInstruction(ReturnType); |
+ setNextLocalInstIndex(nullptr); |
return; |
} |
- } else { |
+ } else { // Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL_INDIRECT |
+ // There is no signature. Assume defined by parameter types. |
ReturnType = Context->getSimpleTypeByID(Values[2]); |
+ if (!isIRGenerationDisabled() && Callee != nullptr) |
+ isValidPointerType(Callee, "Call indirect"); |
+ } |
+ |
+ if (Callee == nullptr && !isIRGenerationDisabled()) |
+ return; |
+ |
+ // Extract out the the call parameters. |
+ SmallVector<Ice::Operand*, 8> Params; |
+ for (Ice::SizeT Index = ParamsStartIndex; Index < Values.size(); ++Index) { |
+ Ice::Operand *Op = getRelativeOperand(Values[Index], BaseIndex); |
+ if (isIRGenerationDisabled()) |
+ continue; |
+ if (Op == nullptr) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Parameter " << (Index - ParamsStartIndex + 1) |
+ << " of " << printName(Fcn) << " is not defined"; |
+ Error(StrBuf.str()); |
+ if (ReturnType != Ice::IceType_void) |
+ setNextLocalInstIndex(nullptr); |
+ return; |
+ } |
+ Params.push_back(Op); |
} |
// Check return type. |
if (IntrinsicInfo == nullptr && !isCallReturnType(ReturnType)) { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Return type of called function is invalid: " << ReturnType; |
+ StrBuf << "Return type of " << printName(Fcn) << " is invalid: " |
+ << ReturnType; |
Error(StrBuf.str()); |
ReturnType = Ice::IceType_i32; |
} |
+ if (isIRGenerationDisabled()) { |
+ if (ReturnType != Ice::IceType_void) |
+ setNextLocalInstIndex(nullptr); |
+ return; |
+ } |
+ |
+ // Type check call parameters. |
+ for (Ice::SizeT Index = 0; Index < Params.size(); ++Index) { |
+ Ice::Operand *Op = Params[Index]; |
+ Ice::Type OpType = Op->getType(); |
+ if (Signature) |
+ verifyCallArgTypeMatches( |
+ Fcn, Index, OpType, Signature->getArgType(Index)); |
+ if (IntrinsicInfo) { |
+ verifyCallArgTypeMatches(Fcn, Index, OpType, |
+ IntrinsicInfo->getArgType(Index)); |
+ } else if (!isCallParameterType(OpType)) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Argument " << *Op << " of " << printName(Fcn) |
+ << " has invalid type: " << Op->getType(); |
+ Error(StrBuf.str()); |
+ appendErrorInstruction(ReturnType); |
+ } |
+ } |
+ |
// Extract call information. |
uint64_t CCInfo = Values[0]; |
CallingConv::ID CallingConv; |
@@ -2709,127 +2797,25 @@ void FunctionParser::ProcessRecord() { |
StrBuf << "Function call calling convention value " << (CCInfo >> 1) |
<< " not understood."; |
Error(StrBuf.str()); |
- if (ReturnType != Ice::IceType_void) |
- appendErrorInstruction(ReturnType); |
+ appendErrorInstruction(ReturnType); |
return; |
} |
bool IsTailCall = static_cast<bool>(CCInfo & 1); |
- Ice::SizeT NumParams = Values.size() - ParamsStartIndex; |
- if (Signature && NumParams != Signature->getNumArgs()) { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Call has " << NumParams |
- << " parameters. Signature expects: " << Signature->getNumArgs(); |
- Error(StrBuf.str()); |
- // Error recover by only checking parameters in both signature and call. |
- NumParams = std::min(NumParams, Signature->getNumArgs()); |
- } |
- if (isIRGenerationDisabled()) { |
- assert(Callee == nullptr); |
- // Check that parameters are defined. |
- for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) { |
- assert(getRelativeOperand(Values[ParamsStartIndex + ParamIndex], |
- BaseIndex) == nullptr); |
- } |
- // Define value slot only if value returned. |
- if (ReturnType != Ice::IceType_void) |
- setNextLocalInstIndex(nullptr); |
- return; |
- } |
+ |
// Create the call instruction. |
Ice::Variable *Dest = (ReturnType == Ice::IceType_void) |
? nullptr |
: getNextInstVar(ReturnType); |
std::unique_ptr<Ice::InstCall> Inst; |
if (IntrinsicInfo) { |
- Inst.reset(Ice::InstIntrinsicCall::create(Func.get(), NumParams, Dest, |
+ Inst.reset(Ice::InstIntrinsicCall::create(Func.get(), Params.size(), Dest, |
Callee, IntrinsicInfo->Info)); |
} else { |
- Inst.reset(Ice::InstCall::create(Func.get(), NumParams, Dest, Callee, |
+ Inst.reset(Ice::InstCall::create(Func.get(), Params.size(), Dest, Callee, |
IsTailCall)); |
} |
- |
- // Add parameters. |
- for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) { |
- Ice::Operand *Op = |
- getRelativeOperand(Values[ParamsStartIndex + ParamIndex], BaseIndex); |
- if (Op == nullptr) { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Parameter " << ParamIndex << " of call not defined"; |
- Error(StrBuf.str()); |
- if (ReturnType != Ice::IceType_void) |
- appendErrorInstruction(ReturnType); |
- return; |
- } |
- |
- // Check that parameter type is valid. |
- if (Signature) { |
- if (Op->getType() != Signature->getArgType(ParamIndex)) { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Call argument " << *Op << " expects " |
- << Signature->getArgType(ParamIndex) |
- << ". Found: " << Op->getType(); |
- Error(StrBuf.str()); |
- } else if (IntrinsicInfo == nullptr && |
- !isCallParameterType(Op->getType())) { |
- // TODO(kschimpf): Move this check to the function declaration, so |
- // that it only needs to be checked once. |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Call argument " << *Op |
- << " matches declaration but has invalid type: " |
- << Op->getType(); |
- Error(StrBuf.str()); |
- } |
- } else if (!isCallParameterType(Op->getType())) { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Call argument " << *Op |
- << " has invalid type: " << Op->getType(); |
- Error(StrBuf.str()); |
- } |
- Inst->addArg(Op); |
- } |
- |
- // If intrinsic call, validate call signature. |
- if (IntrinsicInfo) { |
- Ice::SizeT ArgIndex = 0; |
- switch (IntrinsicInfo->validateCall(Inst.get(), ArgIndex)) { |
- case Ice::Intrinsics::IsValidCall: |
- break; |
- case Ice::Intrinsics::BadReturnType: { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Intrinsic " << Fcn->getName() << " expects return type" |
- << IntrinsicInfo->getReturnType() |
- << ". Found: " << Inst->getReturnType(); |
- Error(StrBuf.str()); |
- break; |
- } |
- case Ice::Intrinsics::WrongNumOfArgs: { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Intrinsic " << Fcn->getName() << " expects " |
- << IntrinsicInfo->getNumArgs() |
- << ". Found: " << Inst->getNumArgs(); |
- Error(StrBuf.str()); |
- break; |
- } |
- case Ice::Intrinsics::WrongCallArgType: { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Intrinsic " << Fcn->getName() << " expects " |
- << IntrinsicInfo->getArgType(ArgIndex) << " for argument " |
- << (ArgIndex + 1) |
- << ". Found: " << Inst->getArg(ArgIndex)->getType(); |
- Error(StrBuf.str()); |
- break; |
- } |
- } |
- } |
- |
+ for (Ice::Operand *Param : Params) |
+ Inst->addArg(Param); |
CurrentNode->appendInst(Inst.release()); |
return; |
} |