Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: src/PNaClTranslator.cpp

Issue 625243002: Convert Subzero's bitcode reader to generate ICE types. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix nits. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceTypes.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
« no previous file with comments | « src/IceTypes.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698