Chromium Code Reviews| Index: src/PNaClTranslator.cpp |
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
| index bde906ab8bee81be43aecfe6bb1f611ace8b6628..f2fcb4e9f51cf7eec40675df733514aacad6bb87 100644 |
| --- a/src/PNaClTranslator.cpp |
| +++ b/src/PNaClTranslator.cpp |
| @@ -20,11 +20,13 @@ |
| #include "IceInst.h" |
| #include "IceOperand.h" |
| #include "IceTypeConverter.h" |
| +#include "llvm/Analysis/NaCl/PNaClABIProps.h" |
| #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" |
| #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
| #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" |
| #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| #include "llvm/IR/Constants.h" |
| +#include "llvm/IR/DataLayout.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Support/Format.h" |
| @@ -55,9 +57,10 @@ public: |
| NaClBitcodeHeader &Header, NaClBitstreamCursor &Cursor, |
| bool &ErrorStatus) |
| : NaClBitcodeParser(Cursor), Translator(Translator), |
| - Mod(new Module(InputName, getGlobalContext())), Header(Header), |
| - TypeConverter(getLLVMContext()), ErrorStatus(ErrorStatus), NumErrors(0), |
| - NumFunctionIds(0), NumFunctionBlocks(0), |
| + Mod(new Module(InputName, getGlobalContext())), DL(PNaClDataLayout), |
| + Header(Header), TypeConverter(getLLVMContext()), |
| + ErrorStatus(ErrorStatus), NumErrors(0), NumFunctionIds(0), |
| + NumFunctionBlocks(0), |
| GlobalVarPlaceHolderType(convertToLLVMType(Ice::IceType_i8)) { |
| Mod->setDataLayout(PNaClDataLayout); |
| } |
| @@ -84,6 +87,8 @@ public: |
| /// Returns the LLVM module associated with the translation. |
| Module *getModule() const { return Mod.get(); } |
| + const DataLayout &getDataLayout() const { return DL; } |
| + |
| /// Returns the number of bytes in the bitcode header. |
| size_t getHeaderSize() const { return Header.getHeaderSize(); } |
| @@ -228,6 +233,8 @@ private: |
| Ice::Translator &Translator; |
| // The parsed module. |
| OwningPtr<Module> Mod; |
| + // The data layout to use. |
| + DataLayout DL; |
| // The bitcode header. |
| NaClBitcodeHeader &Header; |
| // Converter between LLVM and ICE types. |
| @@ -848,6 +855,24 @@ private: |
| // Upper limit of alignment power allowed by LLVM |
| static const uint64_t AlignPowerLimit = 29; |
| + // Extracts the corresponding Alignment to use, given the AlignPower |
| + // (i.e. 2**AlignPower, or 0 if AlignPower == 0). InstName is the |
| + // name of the instruction the alignment appears in. |
|
Jim Stichnoth
2014/09/10 20:27:15
Document that it returns true on success?
Karl
2014/09/10 21:36:29
Modified to always error recover, even on error, s
|
| + bool extractAlignment(const char *InstName, uint64_t AlignPower, |
| + unsigned &Alignment) { |
| + Alignment = 1; |
| + if (AlignPower <= AlignPowerLimit) { |
| + Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1; |
| + return true; |
| + } |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << InstName << " alignment greater than 2**" << AlignPowerLimit |
| + << ". Found: 2**" << AlignPower; |
| + Error(StrBuf.str()); |
| + return false; |
| + } |
| + |
| virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE; |
| virtual void ProcessRecord() LLVM_OVERRIDE; |
| @@ -959,8 +984,8 @@ private: |
| } |
| // Checks if floating arithmetic Op, for type OpTy, is valid. |
| - // Returns false if valid. Otherwise generates an error message and |
| - // returns true. |
| + // Returns true if valid. Otherwise generates an error message and |
| + // returns false; |
| bool isValidFloatingArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) { |
| if (Ice::isFloatingType(OpTy)) |
| return true; |
| @@ -968,6 +993,52 @@ private: |
| return false; |
| } |
| + // Checks if the type of operand Op is the valid pointer type, for |
| + // the given InstructionName. Returns true if valid. Otherwise |
| + // generates an error message and returns false. |
| + bool isValidPointerType(Ice::Operand *Op, const char *InstructionName) { |
| + Ice::Type PtrType = Context->getIcePointerType(); |
| + if (Op->getType() == PtrType) |
| + return true; |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << InstructionName << " address not " << PtrType |
| + << ". Found: " << Op; |
| + Error(StrBuf.str()); |
| + return false; |
| + } |
| + |
| + // Checks if loading/storing a value of type Ty is allowed. |
| + // Returns true if Valid. Otherwise generates an error message and |
| + // returns false. |
| + bool isValidLoadStoreType(Ice::Type Ty, const char *InstructionName) { |
| + if (isLoadStoreType(Ty)) |
| + return true; |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << InstructionName << " type not allowed: " << Ty << "*"; |
| + Error(StrBuf.str()); |
| + return false; |
| + } |
| + |
| + // Checks if loading/storing wa value of type Ty, is allowed for |
|
Jim Stichnoth
2014/09/10 20:27:15
wa --> a
also, no comma
Karl
2014/09/10 21:36:28
Done.
|
| + // the given Alignment. Otherwise generates an error message and |
| + // returns false. |
| + bool isValidLoadStoreAlignment(unsigned Alignment, Ice::Type Ty, |
| + const char *InstructionName) { |
| + if (!isValidLoadStoreType(Ty, InstructionName)) |
| + return false; |
| + if (PNaClABIProps::isAllowedAlignment(&Context->getDataLayout(), Alignment, |
| + Context->convertToLLVMType(Ty))) |
| + return true; |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << InstructionName << " " << Ty << "*: not allowed for alignment " |
| + << Alignment; |
| + Error(StrBuf.str()); |
| + return false; |
| + } |
| + |
| // Reports that the given binary Opcode, for the given type Ty, |
| // is not understood. |
| void ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty); |
| @@ -1529,22 +1600,52 @@ void FunctionParser::ProcessRecord() { |
| Error(StrBuf.str()); |
| return; |
| } |
| - uint64_t AlignPower = Values[1]; |
| - unsigned Alignment = 1; |
| - if (AlignPower <= AlignPowerLimit) { |
| - Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1; |
| - } else { |
| - std::string Buffer; |
| - raw_string_ostream StrBuf(Buffer); |
| - StrBuf << "Alloca on alignment greater than 2**" << AlignPowerLimit |
| - << ". Found: 2**" << AlignPower; |
| - Error(StrBuf.str()); |
| + unsigned Alignment; |
| + if (!extractAlignment("Alloca", Values[1], Alignment)) { |
| // TODO(kschimpf) Remove error recovery once implementation complete. |
|
Jim Stichnoth
2014/09/10 20:27:15
Can this TODO be removed now? Or does it belong i
Karl
2014/09/10 21:36:29
Modified so that the error recovery done inside ex
|
| + Alignment = 1; |
| } |
| Ice::Variable *Dest = NextInstVar(Context->getIcePointerType()); |
| Inst = Ice::InstAlloca::create(Func, ByteCount, Alignment, Dest); |
| break; |
| } |
| + case naclbitc::FUNC_CODE_INST_LOAD: { |
| + // LOAD: [address, align, ty] |
| + if (!isValidRecordSize(3, "function block load")) |
| + return; |
| + Ice::Operand *Address = getRelativeOperand(Values[0]); |
| + if (!isValidPointerType(Address, "Load")) |
| + return; |
| + unsigned Alignment; |
| + if (!extractAlignment("Store", Values[1], Alignment)) { |
|
Jim Stichnoth
2014/09/10 20:27:15
"Load"
Karl
2014/09/10 21:36:28
Done.
|
| + // TODO(kschimpf) Remove error recovery once implementation complete. |
| + Alignment = 1; |
| + } |
| + Ice::Type Ty = Context->convertToIceType(Context->getTypeByID(Values[2])); |
| + if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) |
| + return; |
| + Ice::Variable *Dest = NextInstVar(Ty); |
| + Inst = Ice::InstLoad::create(Func, Dest, Address, Alignment); |
| + break; |
| + } |
| + case naclbitc::FUNC_CODE_INST_STORE: { |
| + // STORE: [address, value, align] |
| + if (!isValidRecordSize(3, "function block store")) |
| + return; |
| + Ice::Operand *Address = getRelativeOperand(Values[0]); |
| + if (!isValidPointerType(Address, "Store")) |
| + return; |
| + Ice::Operand *Value = getRelativeOperand(Values[1]); |
| + unsigned Alignment; |
| + if (!extractAlignment("Store", Values[2], Alignment)) { |
| + // TODO(kschimpf) Remove error recovery once implementation complete. |
| + Alignment = 1; |
| + } |
| + if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) |
| + return; |
| + Inst = Ice::InstStore::create(Func, Value, Address, Alignment); |
| + break; |
| + } |
| default: |
| // Generate error message! |
| BlockParserBaseClass::ProcessRecord(); |