Index: src/PNaClTranslator.cpp |
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
index 76368d9bc868c33ffef3afe07ed7b73a2f22db0b..15272c11d4e8ee6bc75a7bd08f844ec5c54480d2 100644 |
--- a/src/PNaClTranslator.cpp |
+++ b/src/PNaClTranslator.cpp |
@@ -46,6 +46,114 @@ static cl::opt<bool> AllowErrorRecovery( |
cl::desc("Allow error recovery when reading PNaCl bitcode."), |
cl::init(false)); |
+// Models elements in the list of types defined in the types block. |
+// These elements can be undefined, a (simple) type, or a function type |
+// signature. Note that an extended type is undefined on construction. |
+// Use methods setAsSimpleType and setAsFuncSigType to define |
+// the extended type. |
+class ExtendedType { |
+ // ExtendedType(const ExtendedType &Ty) = delete; |
+ ExtendedType &operator=(const ExtendedType &Ty) = delete; |
+public: |
+ /// Discriminator for LLVM-style RTTI. |
+ enum TypeKind { Undefined, Simple, FuncSig }; |
+ |
+ ExtendedType() : Kind(Undefined) {} |
+ |
+ virtual ~ExtendedType() {} |
+ |
+ ExtendedType::TypeKind getKind() const { return Kind; } |
+ void Dump(Ice::Ostream &Stream) const; |
+ |
+ /// Changes the extended type to a simple type with the given |
+ /// value. |
+ void setAsSimpleType(Ice::Type Ty) { |
+ assert(Kind == Undefined); |
+ Kind = Simple; |
+ Signature.setReturnType(Ty); |
+ } |
+ |
+ /// Changes the extended type to an (empty) function signature type. |
+ void setAsFunctionType() { |
+ assert(Kind == Undefined); |
+ Kind = FuncSig; |
+ } |
+ |
+protected: |
+ // Note: For simple types, the return type of the signature will |
+ // be used to hold the simple type. |
+ Ice::FuncSigType Signature; |
+ |
+private: |
+ ExtendedType::TypeKind Kind; |
+}; |
+ |
+Ice::Ostream &operator<<(Ice::Ostream &Stream, const ExtendedType &Ty) { |
+ Ty.Dump(Stream); |
+ return Stream; |
+} |
+ |
+Ice::Ostream &operator<<(Ice::Ostream &Stream, ExtendedType::TypeKind Kind) { |
+ Stream << "ExtendedType::"; |
+ switch (Kind) { |
+ case ExtendedType::Undefined: |
+ Stream << "Undefined"; |
+ break; |
+ case ExtendedType::Simple: |
+ Stream << "Simple"; |
+ break; |
+ case ExtendedType::FuncSig: |
+ Stream << "FuncSig"; |
+ break; |
+ default: |
+ Stream << "??"; |
+ break; |
+ } |
+ return Stream; |
+} |
+ |
+// Models an ICE type as an extended type. |
+class SimpleExtendedType : public ExtendedType { |
+ SimpleExtendedType(const SimpleExtendedType &) = delete; |
+ SimpleExtendedType &operator=(const SimpleExtendedType &) = delete; |
+public: |
+ Ice::Type getType() const { return Signature.getReturnType(); } |
+ |
+ static bool classof(const ExtendedType *Ty) { |
+ return Ty->getKind() == Simple; |
+ } |
+}; |
+ |
+// Models a function signature as an extended type. |
+class FuncSigExtendedType : public ExtendedType { |
+ FuncSigExtendedType(const FuncSigExtendedType &) = delete; |
+ FuncSigExtendedType &operator=(const FuncSigExtendedType &) = delete; |
+public: |
+ const Ice::FuncSigType &getSignature() const { return Signature; } |
+ void setReturnType(Ice::Type ReturnType) { |
+ Signature.setReturnType(ReturnType); |
+ } |
+ void appendArgType(Ice::Type ArgType) { Signature.appendArgType(ArgType); } |
+ static bool classof(const ExtendedType *Ty) { |
+ return Ty->getKind() == FuncSig; |
+ } |
+}; |
+ |
+void ExtendedType::Dump(Ice::Ostream &Stream) const { |
+ Stream << Kind; |
+ switch (Kind) { |
+ case Simple: { |
+ Stream << " " << Signature.getReturnType(); |
+ break; |
+ } |
+ case FuncSig: { |
+ Stream << " " << Signature; |
+ } |
+ default: |
+ break; |
+ } |
+} |
+ |
// Top-level class to read PNaCl bitcode files, and translate to ICE. |
class TopLevelParser : public NaClBitcodeParser { |
TopLevelParser(const TopLevelParser &) = delete; |
@@ -96,23 +204,35 @@ public: |
/// Changes the size of the type list to the given size. |
void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); } |
- /// Returns the type associated with the given index. |
- Type *getTypeByID(unsigned ID) { |
- // Note: method resizeTypeIDValues expands TypeIDValues |
- // to the specified size, and fills elements with nullptr. |
- Type *Ty = ID < TypeIDValues.size() ? TypeIDValues[ID] : nullptr; |
+ /// Returns the undefined type associated with type ID. |
+ /// Note: Returns extended type ready to be defined. |
+ ExtendedType *getTypeByIDForDefining(unsigned ID) { |
+ // Get corresponding element, verifying the value is still undefined |
+ // (and hence allowed to be defined). |
+ ExtendedType *Ty = getTypeByIDAsKind(ID, ExtendedType::Undefined); |
if (Ty) |
return Ty; |
- return reportTypeIDAsUndefined(ID); |
+ if (ID >= TypeIDValues.size()) |
+ TypeIDValues.resize(ID+1); |
+ return &TypeIDValues[ID]; |
} |
- /// Defines type for ID. |
- void setTypeID(unsigned ID, Type *Ty) { |
- if (ID < TypeIDValues.size() && TypeIDValues[ID] == nullptr) { |
- TypeIDValues[ID] = Ty; |
- return; |
- } |
- reportBadSetTypeID(ID, Ty); |
+ /// Returns the type associated with the given index. |
+ Ice::Type getSimpleTypeByID(unsigned ID) { |
+ const ExtendedType *Ty = getTypeByIDAsKind(ID, ExtendedType::Simple); |
+ if (Ty == nullptr) |
+ // Return error recovery value. |
+ return Ice::IceType_void; |
+ return cast<SimpleExtendedType>(Ty)->getType(); |
+ } |
+ |
+ /// Returns the type signature associated with the given index. |
+ const Ice::FuncSigType &getFuncSigTypeByID(unsigned ID) { |
+ const ExtendedType *Ty = getTypeByIDAsKind(ID, ExtendedType::FuncSig); |
+ if (Ty == nullptr) |
+ // Return error recovery value. |
+ return UndefinedFuncSigType; |
+ return cast<FuncSigExtendedType>(Ty)->getSignature(); |
} |
/// Sets the next function ID to the given LLVM function. |
@@ -137,7 +257,7 @@ public: |
return DefiningFunctionsList[NumFunctionBlocks++]; |
} |
- /// Returns the LLVM IR value associatd with the global value ID. |
+ /// Returns the LLVM Function address associated with ID. |
Function *getFunctionByID(unsigned ID) const { |
if (ID >= FunctionIDValues.size()) |
return nullptr; |
@@ -241,18 +361,6 @@ public: |
return TypeConverter.convertToLLVMType(IceTy); |
} |
- /// Returns the LLVM integer type with the given number of Bits. If |
- /// Bits is not a valid PNaCl type, returns nullptr. |
- Type *getLLVMIntegerType(unsigned Bits) const { |
- return TypeConverter.getLLVMIntegerType(Bits); |
- } |
- |
- /// Returns the LLVM vector with the given Size and Ty. If not a |
- /// valid PNaCl vector type, returns nullptr. |
- Type *getLLVMVectorType(unsigned Size, Ice::Type Ty) const { |
- return TypeConverter.getLLVMVectorType(Size, Ty); |
- } |
- |
/// Returns the model for pointer types in ICE. |
Ice::Type getIcePointerType() const { |
return TypeConverter.getIcePointerType(); |
@@ -274,7 +382,7 @@ private: |
// The number of errors reported. |
unsigned NumErrors; |
// The types associated with each type ID. |
- std::vector<Type *> TypeIDValues; |
+ std::vector<ExtendedType> TypeIDValues; |
// The set of function value IDs. |
std::vector<WeakVH> FunctionIDValues; |
// The set of global addresses IDs. |
@@ -289,43 +397,45 @@ private: |
// The list of value IDs (in the order found) of defining function |
// addresses. |
std::vector<unsigned> DefiningFunctionsList; |
+ // Error recovery value to use when getFuncSigTypeByID fails. |
+ Ice::FuncSigType UndefinedFuncSigType; |
bool ParseBlock(unsigned BlockID) override; |
- /// Reports that type ID is undefined, and then returns |
- /// the void type. |
- Type *reportTypeIDAsUndefined(unsigned ID); |
+ // Gets extended type associated with the given index, assuming the |
+ // extended type is of the WantedKind. Generates error message if |
+ // corresponding extended type of WantedKind can't be found, and |
+ // returns nullptr. |
+ ExtendedType *getTypeByIDAsKind(unsigned ID, |
+ ExtendedType::TypeKind WantedKind) { |
+ ExtendedType *Ty = nullptr; |
+ if (ID < TypeIDValues.size()) { |
+ Ty = &TypeIDValues[ID]; |
+ if (Ty->getKind() == WantedKind) |
+ return Ty; |
+ } |
+ // Generate an error message and set ErrorStatus. |
+ this->reportBadTypeIDAs(ID, Ty, WantedKind); |
+ return nullptr; |
+ } |
- /// Reports error about bad call to setTypeID. |
- void reportBadSetTypeID(unsigned ID, Type *Ty); |
+ // Reports that type ID is undefined, or not of the WantedType. |
+ void reportBadTypeIDAs(unsigned ID, const ExtendedType *Ty, |
+ ExtendedType::TypeKind WantedType); |
// Reports that there is no corresponding ICE type for LLVMTy, and |
// returns ICE::IceType_void. |
Ice::Type convertToIceTypeError(Type *LLVMTy); |
}; |
-Type *TopLevelParser::reportTypeIDAsUndefined(unsigned ID) { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Can't find type for type id: " << ID; |
- Error(StrBuf.str()); |
- // TODO(kschimpf) Remove error recovery once implementation complete. |
- Type *Ty = TypeConverter.convertToLLVMType(Ice::IceType_void); |
- // To reduce error messages, update type list if possible. |
- if (ID < TypeIDValues.size()) |
- TypeIDValues[ID] = Ty; |
- return Ty; |
-} |
- |
-void TopLevelParser::reportBadSetTypeID(unsigned ID, Type *Ty) { |
+void TopLevelParser::reportBadTypeIDAs(unsigned ID, const ExtendedType *Ty, |
+ ExtendedType::TypeKind WantedType) { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
- if (ID >= TypeIDValues.size()) { |
- StrBuf << "Type index " << ID << " out of range: can't install."; |
+ if (Ty == nullptr) { |
+ StrBuf << "Can't find extended type for type id: " << ID; |
} else { |
- // Must be case that index already defined. |
- StrBuf << "Type index " << ID << " defined as " << *TypeIDValues[ID] |
- << " and " << *Ty << "."; |
+ StrBuf << "Type id " << ID << " not " << WantedType << ". Found: " << *Ty; |
} |
Error(StrBuf.str()); |
} |
@@ -482,10 +592,13 @@ private: |
unsigned NextTypeId; |
void ProcessRecord() override; |
+ |
+ void setNextTypeIDAsSimpleType(Ice::Type Ty) { |
+ Context->getTypeByIDForDefining(NextTypeId++)->setAsSimpleType(Ty); |
+ } |
}; |
void TypesParser::ProcessRecord() { |
- Type *Ty = nullptr; |
const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
switch (Record.GetCode()) { |
case naclbitc::TYPE_CODE_NUMENTRY: |
@@ -498,71 +611,140 @@ void TypesParser::ProcessRecord() { |
// VOID |
if (!isValidRecordSize(0, "Type void")) |
return; |
- Ty = Context->convertToLLVMType(Ice::IceType_void); |
- break; |
+ setNextTypeIDAsSimpleType(Ice::IceType_void); |
+ return; |
case naclbitc::TYPE_CODE_FLOAT: |
// FLOAT |
if (!isValidRecordSize(0, "Type float")) |
return; |
- Ty = Context->convertToLLVMType(Ice::IceType_f32); |
- break; |
+ setNextTypeIDAsSimpleType(Ice::IceType_f32); |
+ return; |
case naclbitc::TYPE_CODE_DOUBLE: |
// DOUBLE |
if (!isValidRecordSize(0, "Type double")) |
return; |
- Ty = Context->convertToLLVMType(Ice::IceType_f64); |
- break; |
+ setNextTypeIDAsSimpleType(Ice::IceType_f64); |
+ return; |
case naclbitc::TYPE_CODE_INTEGER: |
// INTEGER: [width] |
if (!isValidRecordSize(1, "Type integer")) |
return; |
- Ty = Context->getLLVMIntegerType(Values[0]); |
- if (Ty == nullptr) { |
+ switch (Values[0]) { |
+ case 1: |
+ setNextTypeIDAsSimpleType(Ice::IceType_i1); |
+ return; |
+ case 8: |
+ setNextTypeIDAsSimpleType(Ice::IceType_i8); |
+ return; |
+ case 16: |
+ setNextTypeIDAsSimpleType(Ice::IceType_i16); |
+ return; |
+ case 32: |
+ setNextTypeIDAsSimpleType(Ice::IceType_i32); |
+ return; |
+ case 64: |
+ setNextTypeIDAsSimpleType(Ice::IceType_i64); |
+ return; |
+ default: |
+ break; |
+ } |
+ { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
StrBuf << "Type integer record with invalid bitsize: " << Values[0]; |
Error(StrBuf.str()); |
- // TODO(kschimpf) Remove error recovery once implementation complete. |
- // Fix type so that we can continue. |
- Ty = Context->convertToLLVMType(Ice::IceType_i32); |
} |
- break; |
+ return; |
case naclbitc::TYPE_CODE_VECTOR: { |
// VECTOR: [numelts, eltty] |
if (!isValidRecordSize(2, "Type vector")) |
return; |
- Type *BaseTy = Context->getTypeByID(Values[1]); |
- Ty = Context->getLLVMVectorType(Values[0], |
- Context->convertToIceType(BaseTy)); |
- if (Ty == nullptr) { |
+ Ice::Type BaseTy = Context->getSimpleTypeByID(Values[1]); |
+ Ice::SizeT Size = Values[0]; |
+ switch (BaseTy) { |
+ case Ice::IceType_i1: |
+ switch (Size) { |
+ case 4: |
+ setNextTypeIDAsSimpleType(Ice::IceType_v4i1); |
+ return; |
+ case 8: |
+ setNextTypeIDAsSimpleType(Ice::IceType_v8i1); |
+ return; |
+ case 16: |
+ setNextTypeIDAsSimpleType(Ice::IceType_v16i1); |
+ return; |
+ default: |
+ break; |
+ } |
+ break; |
+ case Ice::IceType_i8: |
+ if (Size == 16) { |
+ setNextTypeIDAsSimpleType(Ice::IceType_v16i8); |
+ return; |
+ } |
+ break; |
+ case Ice::IceType_i16: |
+ if (Size == 8) { |
+ setNextTypeIDAsSimpleType(Ice::IceType_v8i16); |
+ return; |
+ } |
+ break; |
+ case Ice::IceType_i32: |
+ if (Size == 4) { |
+ setNextTypeIDAsSimpleType(Ice::IceType_v4i32); |
+ return; |
+ } |
+ break; |
+ case Ice::IceType_f32: |
+ if (Size == 4) { |
+ setNextTypeIDAsSimpleType(Ice::IceType_v4f32); |
+ return; |
+ } |
+ break; |
+ default: |
+ break; |
+ } |
+ { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Invalid type vector record: <" << Values[0] << " x " << *BaseTy |
+ StrBuf << "Invalid type vector record: <" << Values[0] << " x " << BaseTy |
<< ">"; |
Error(StrBuf.str()); |
- Ty = Context->convertToLLVMType(Ice::IceType_void); |
} |
- break; |
+ return; |
} |
case naclbitc::TYPE_CODE_FUNCTION: { |
// FUNCTION: [vararg, retty, paramty x N] |
if (!isValidRecordSizeAtLeast(2, "Type signature")) |
return; |
- SmallVector<Type *, 8> ArgTys; |
+ if (Values[0]) |
+ Error("Function type can't define varargs"); |
+ ExtendedType *Ty = Context->getTypeByIDForDefining(NextTypeId++); |
+ Ty->setAsFunctionType(); |
+ FuncSigExtendedType *FuncTy = cast<FuncSigExtendedType>(Ty); |
+ FuncTy->setReturnType(Context->getSimpleTypeByID(Values[1])); |
for (unsigned i = 2, e = Values.size(); i != e; ++i) { |
- ArgTys.push_back(Context->getTypeByID(Values[i])); |
+ // Check that type void not used as argument type. |
+ // Note: PNaCl restrictions can't be checked until we |
+ // know the name, because we have to check for intrinsic signatures. |
+ Ice::Type ArgTy = Context->getSimpleTypeByID(Values[i]); |
+ if (ArgTy == Ice::IceType_void) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Type for parameter " << (i - 1) |
+ << " not valid. Found: " << ArgTy; |
+ // TODO(kschimpf) Remove error recovery once implementation complete. |
+ ArgTy = Ice::IceType_i32; |
+ } |
+ FuncTy->appendArgType(ArgTy); |
} |
- Ty = FunctionType::get(Context->getTypeByID(Values[1]), ArgTys, Values[0]); |
- break; |
+ return; |
} |
default: |
BlockParserBaseClass::ProcessRecord(); |
return; |
} |
- // If Ty not defined, assume error. Use void as filler. |
- if (Ty == nullptr) |
- Ty = Context->convertToLLVMType(Ice::IceType_void); |
- Context->setTypeID(NextTypeId++, Ty); |
+ llvm_unreachable("Unknown type block record not processed!"); |
} |
/// Parses the globals block (i.e. global variables). |
@@ -1427,7 +1609,7 @@ void FunctionParser::ProcessRecord() { |
if (!isValidRecordSize(3, "function block cast")) |
return; |
Ice::Operand *Src = getRelativeOperand(Values[0], BaseIndex); |
- Type *CastType = Context->getTypeByID(Values[1]); |
+ Ice::Type CastType = Context->getSimpleTypeByID(Values[1]); |
Instruction::CastOps LLVMCastOp; |
Ice::InstCast::OpKind CastKind; |
if (!naclbitc::DecodeCastOpcode(Values[2], LLVMCastOp) || |
@@ -1438,18 +1620,18 @@ void FunctionParser::ProcessRecord() { |
Error(StrBuf.str()); |
return; |
} |
- Type *SrcType = Context->convertToLLVMType(Src->getType()); |
- if (!CastInst::castIsValid(LLVMCastOp, SrcType, CastType)) { |
+ Ice::Type SrcType = Src->getType(); |
+ if (!CastInst::castIsValid(LLVMCastOp, Context->convertToLLVMType(SrcType), |
+ Context->convertToLLVMType(CastType))) { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
StrBuf << "Illegal cast: " << Instruction::getOpcodeName(LLVMCastOp) |
- << " " << *SrcType << " to " << *CastType; |
+ << " " << SrcType << " to " << CastType; |
Error(StrBuf.str()); |
return; |
} |
- CurrentNode->appendInst(Ice::InstCast::create( |
- Func, CastKind, getNextInstVar(Context->convertToIceType(CastType)), |
- Src)); |
+ CurrentNode->appendInst( |
+ Ice::InstCast::create(Func, CastKind, getNextInstVar(CastType), Src)); |
break; |
} |
case naclbitc::FUNC_CODE_INST_VSELECT: { |
@@ -1669,8 +1851,7 @@ void FunctionParser::ProcessRecord() { |
// already frozen when the problem was noticed. |
if (!isValidRecordSizeAtLeast(4, "function block switch")) |
return; |
- Ice::Type CondTy = |
- Context->convertToIceType(Context->getTypeByID(Values[0])); |
+ Ice::Type CondTy = Context->getSimpleTypeByID(Values[0]); |
if (!Ice::isScalarIntegerType(CondTy)) { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
@@ -1738,7 +1919,7 @@ void FunctionParser::ProcessRecord() { |
Error(StrBuf.str()); |
return; |
} |
- Ice::Type Ty = Context->convertToIceType(Context->getTypeByID(Values[0])); |
+ Ice::Type Ty = Context->getSimpleTypeByID(Values[0]); |
if (Ty == Ice::IceType_void) { |
Error("Phi record using type void not allowed"); |
return; |
@@ -1789,7 +1970,7 @@ void FunctionParser::ProcessRecord() { |
return; |
unsigned Alignment; |
extractAlignment("Load", Values[1], Alignment); |
- Ice::Type Ty = Context->convertToIceType(Context->getTypeByID(Values[2])); |
+ Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); |
if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) |
return; |
CurrentNode->appendInst( |
@@ -1881,7 +2062,7 @@ void FunctionParser::ProcessRecord() { |
} |
} |
} else { |
- ReturnType = Context->convertToIceType(Context->getTypeByID(Values[2])); |
+ ReturnType = Context->getSimpleTypeByID(Values[2]); |
} |
// Create the call instruction. |
@@ -1953,8 +2134,7 @@ void FunctionParser::ProcessRecord() { |
// FORWARDTYPEREF: [opval, ty] |
if (!isValidRecordSize(2, "function block forward type ref")) |
return; |
- setOperand(Values[0], createInstVar(Context->convertToIceType( |
- Context->getTypeByID(Values[1])))); |
+ setOperand(Values[0], createInstVar(Context->getSimpleTypeByID(Values[1]))); |
break; |
} |
default: |
@@ -2003,8 +2183,7 @@ void ConstantsParser::ProcessRecord() { |
// SETTYPE: [typeid] |
if (!isValidRecordSize(1, "constants block set type")) |
return; |
- NextConstantType = |
- Context->convertToIceType(Context->getTypeByID(Values[0])); |
+ NextConstantType = Context->getSimpleTypeByID(Values[0]); |
if (NextConstantType == Ice::IceType_void) |
Error("constants block set type not allowed for void type"); |
return; |
@@ -2298,15 +2477,7 @@ void ModuleParser::ProcessRecord() { |
// FUNCTION: [type, callingconv, isproto, linkage] |
if (!isValidRecordSize(4, "Function heading")) |
return; |
- Type *Ty = Context->getTypeByID(Values[0]); |
- FunctionType *FTy = dyn_cast<FunctionType>(Ty); |
- if (FTy == nullptr) { |
- std::string Buffer; |
- raw_string_ostream StrBuf(Buffer); |
- StrBuf << "Function heading expects function type. Found: " << Ty; |
- Error(StrBuf.str()); |
- return; |
- } |
+ const Ice::FuncSigType &Ty = Context->getFuncSigTypeByID(Values[0]); |
CallingConv::ID CallingConv; |
if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) { |
std::string Buffer; |
@@ -2324,7 +2495,14 @@ void ModuleParser::ProcessRecord() { |
Error(StrBuf.str()); |
return; |
} |
- Function *Func = Function::Create(FTy, Linkage, "", Context->getModule()); |
+ SmallVector<Type *, 8> ArgTys; |
+ for (Ice::Type ArgType : Ty.getArgList()) { |
+ ArgTys.push_back(Context->convertToLLVMType(ArgType)); |
+ } |
+ Function *Func = Function::Create( |
+ FunctionType::get(Context->convertToLLVMType(Ty.getReturnType()), |
+ ArgTys, false), |
+ Linkage, "", Context->getModule()); |
Func->setCallingConv(CallingConv); |
if (Values[2] == 0) |
Context->setNextValueIDAsImplementedFunction(); |