Index: src/PNaClTranslator.cpp |
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
index bde906ab8bee81be43aecfe6bb1f611ace8b6628..c83898debeb566f29ca9d56ecc70d58497d30a67 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. |
+ void extractAlignment(const char *InstName, uint64_t AlignPower, |
+ unsigned &Alignment) { |
+ if (AlignPower <= AlignPowerLimit) { |
+ Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1; |
+ return; |
+ } |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << InstName << " alignment greater than 2**" << AlignPowerLimit |
+ << ". Found: 2**" << AlignPower; |
+ Error(StrBuf.str()); |
+ // Error recover with value that is always acceptable. |
+ Alignment = 1; |
+ } |
+ |
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 a value of type Ty is allowed for |
+ // 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,46 @@ 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()); |
- // TODO(kschimpf) Remove error recovery once implementation complete. |
- } |
+ unsigned Alignment; |
+ extractAlignment("Alloca", Values[1], Alignment); |
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; |
+ extractAlignment("Load", Values[1], Alignment); |
+ 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(); |