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

Side by Side Diff: src/PNaClTranslator.cpp

Issue 361733002: Update Subzero to start parsing PNaCl bitcode files. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Use SmallVector to hold data. Created 6 years, 5 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 unified diff | Download patch
OLDNEW
(Empty)
1 //===- subzero/src/PNaClTranslator.cpp - Builds ICE from PNaCl bitcode ----===//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the PNaCl bitcode file to Ice, to machine code
11 // translator.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "PNaClTranslator.h"
16 #include "IceCfg.h"
17 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h"
18 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
19 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
20 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/LLVMContext.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Support/Format.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "llvm/Support/ValueHandle.h"
28
29 #include <vector>
30 #include <cassert>
31
32 using namespace llvm;
33
34 namespace {
35
36 // Top-level class to read PNaCl bitcode files, and translate to ICE.
37 class TopLevelParser : public NaClBitcodeParser {
38 TopLevelParser(const TopLevelParser&) LLVM_DELETED_FUNCTION;
39 TopLevelParser &operator=(const TopLevelParser&) LLVM_DELETED_FUNCTION;
40
41 public:
42 TopLevelParser(const std::string &InputName,
43 NaClBitcodeHeader &Header,
44 NaClBitstreamCursor &Cursor,
45 int &ExitStatusFlag)
46 : NaClBitcodeParser(Cursor),
47 Mod(new Module(InputName, getGlobalContext())),
48 Header(Header),
Jim Stichnoth 2014/07/07 20:50:24 It looks like you didn't run clang-format on this
Karl 2014/07/07 21:50:56 Letting formatter fix this.
49 ExitStatusFlag(ExitStatusFlag),
50 NumErrors(0),
51 NumFunctionIds(0),
52 GlobalVarPlaceHolderType(0) {
Jim Stichnoth 2014/07/07 20:50:24 Use NULL instead of 0 for clarity. (Or just initi
Karl 2014/07/07 21:50:56 Done.
53 Mod->setDataLayout(PNaClDataLayout);
54 GlobalVarPlaceHolderType = Type::getInt8Ty(getLLVMContext());
55 }
56
57 virtual ~TopLevelParser() {} LLVM_OVERRIDE;
58
59 virtual bool Error(const std::string &Message) LLVM_OVERRIDE {
60 ExitStatusFlag = 1;
61 ++NumErrors;
62 return NaClBitcodeParser::Error(Message);
63 }
64
65 /// Returns the number of errors found while parsing the bitcode
66 /// file.
67 unsigned getNumErrors() const {
68 return NumErrors;
69 }
70
71 /// Returns the LLVM module associated with the translation.
72 Module *getModule() const {
73 return Mod.get();
74 }
75
76 /// Returns the number of bytes in the bitcode header.
77 size_t getHeaderSize() const {
78 return Header.getHeaderSize();
79 }
80
81 /// Returns the llvm context to use.
82 LLVMContext &getLLVMContext() const {
83 return Mod->getContext();
84 }
85
86 /// Changes the size of the type list to the given size.
87 void resizeTypeIDValues(unsigned NewSize) {
88 TypeIDValues.resize(NewSize);
89 }
90
91 /// Returns the type associated with the given index.
92 Type *getTypeByID(unsigned ID) {
93 // Note: method resizeTypeIDValues expands TypeIDValues
94 // to the specified size, and fills elements with NULL.
95 Type *Ty = ID < TypeIDValues.size() ? TypeIDValues[ID] : 0;
Jim Stichnoth 2014/07/07 20:50:24 NULL instead of 0 for clarity
Karl 2014/07/07 21:50:56 Done.
96 if (Ty) return Ty;
97 return reportTypeIDAsUndefined(ID);
98 }
99
100 /// Defines type for ID.
101 void setTypeID(unsigned ID, Type *Ty) {
102 if (ID < TypeIDValues.size() && TypeIDValues[ID] == 0) {
Jim Stichnoth 2014/07/07 20:50:24 NULL
Karl 2014/07/07 21:50:55 Done.
103 TypeIDValues[ID] = Ty;
104 return;
105 }
106 reportBadSetTypeID(ID, Ty);
107 }
108
109 /// Sets the next function ID to the given LLVM function.
110 void setNextFunctionID(Function *Fcn) {
111 ++NumFunctionIds;
112 ValueIDValues.push_back(Fcn);
113 }
114
115 /// Defines the next function ID as one that has an implementation
116 /// (i.e a corresponding function block in the bitcode).
117 void setNextValueIDAsImplementedFunction() {
118 DefiningFunctionsList.push_back(ValueIDValues.size());
119 }
120
121 /// Returns the LLVM IR value associatd with the global value ID.
122 Value *getGlobalValueByID(unsigned ID) const {
123 if (ID >= ValueIDValues.size()) return 0;
124 return ValueIDValues[ID];
125 }
126
127 /// Returns the number of function addresses (i.e. ID's) defined in
128 /// the bitcode file.
129 unsigned getNumFunctionIDs() const {
130 return NumFunctionIds;
131 }
132
133 /// Returns the number of global values defined in the bitcode
134 /// file.
135 unsigned getNumGlobalValueIDs() const {
136 return ValueIDValues.size();
137 }
138
139 /// Resizes the list of of value IDs to include Count global
Jim Stichnoth 2014/07/07 20:50:24 of of --> of
Karl 2014/07/07 21:50:56 Done.
140 /// variable IDs.
141 void resizeValueIDsForGlobalVarCount(unsigned Count) {
142 ValueIDValues.resize(ValueIDValues.size() + Count);
143 }
144
145 /// Returns the global variable address associated with the given
146 /// value ID. If the ID refers to a global variable address not yet
147 /// defined, a placeholder is created so that we can fix it up
148 /// later.
149 Constant *getOrCreateGlobalVarRef(unsigned ID) {
150 if (ID >= ValueIDValues.size()) return 0;
151 if (Value *C = ValueIDValues[ID])
152 return dyn_cast<Constant>(C);
153 Constant *C =
154 new GlobalVariable(*Mod, GlobalVarPlaceHolderType, false,
155 GlobalValue::ExternalLinkage, 0);
156 ValueIDValues[ID] = C;
157 return C;
158 }
159
160 /// Assigns the given global variable (address) to the given value
161 /// ID. Returns true if ID is a valid global variable ID. Otherwise
162 /// returns false.
163 bool assignGlobalVariable(GlobalVariable *GV, unsigned ID) {
164 if (ID < NumFunctionIds || ID >= ValueIDValues.size()) return false;
165 WeakVH &OldV = ValueIDValues[ID];
166 if (OldV == 0) {
167 ValueIDValues[ID] = GV;
168 return true;
169 }
170
171 // If reached, there was a forward reference to this value. Replace it.
172 Value *PrevVal = OldV;
173 GlobalVariable *Placeholder = cast<GlobalVariable>(PrevVal);
174 Placeholder->replaceAllUsesWith(
175 ConstantExpr::getBitCast(GV, Placeholder->getType()));
176 Placeholder->eraseFromParent();
177 ValueIDValues[ID] = GV;
178 return true;
179 }
180
181 private:
182 // The parsed module.
183 OwningPtr<Module> Mod;
184 // The bitcode header.
185 NaClBitcodeHeader &Header;
186 // The exit status flag that should be set to 1 if an error occurs.
187 int &ExitStatusFlag;
188 // The number of errors reported.
189 unsigned NumErrors;
190 // The types associated with each type ID.
191 std::vector<Type*> TypeIDValues;
192 // The (global) value IDs.
193 std::vector<WeakVH> ValueIDValues;
194 // The number of function IDs.
195 unsigned NumFunctionIds;
196 // The list of value IDs (in the order found) of defining function
197 // addresses.
198 std::vector<unsigned> DefiningFunctionsList;
199 // Cached global variable placeholder type. Used for all forward
200 // references to global variable addresses.
201 Type *GlobalVarPlaceHolderType;
202
203 virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
204
205 /// Reports that type ID is undefined, and then returns
206 /// the void type.
207 Type *reportTypeIDAsUndefined(unsigned ID);
208
209 /// Reports error about bad call to setTypeID.
210 void reportBadSetTypeID(unsigned ID, Type *Ty);
211 };
212
213 Type *TopLevelParser::reportTypeIDAsUndefined(unsigned ID) {
214 std::string Buffer;
215 raw_string_ostream StrBuf(Buffer);
216 StrBuf << "Can't find type for type id: " << ID;
217 Error(StrBuf.str());
218 Type *Ty = Type::getVoidTy(getLLVMContext());
219 // To reduce error messages, update type list if possible.
220 if (ID < TypeIDValues.size()) TypeIDValues[ID] = Ty;
221 return Ty;
222 }
223
224 void TopLevelParser::reportBadSetTypeID(unsigned ID, Type *Ty) {
225 std::string Buffer;
226 raw_string_ostream StrBuf(Buffer);
227 if (ID >= TypeIDValues.size()) {
228 StrBuf << "Type index " << ID << " out of range: can't install.";
229 } else {
230 // Must be case that index already defined.
231 StrBuf << "Type index " << ID << " defined as " << *TypeIDValues[ID]
232 << " and " << *Ty << ".";
233 }
234 Error(StrBuf.str());
235 }
236
237 // Base class for parsing blocks within the bitcode file. Note:
238 // Because this is the base class of block parsers, we generate error
239 // messages if ParseBlock or ParseRecord is not overridden in derived
240 // classes.
241 class BlockParserBaseClass : public NaClBitcodeParser {
242 public:
243 // Constructor for the top-level module block parser.
244 BlockParserBaseClass(unsigned BlockID, TopLevelParser *Context)
245 : NaClBitcodeParser(BlockID, Context),
246 Context(Context) {}
247
248 virtual ~BlockParserBaseClass() LLVM_OVERRIDE {}
249
250 protected:
251 // The context parser that contains the decoded state.
252 TopLevelParser *Context;
253
254 // Constructor for nested block parsers.
255 BlockParserBaseClass(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
256 : NaClBitcodeParser(BlockID, EnclosingParser),
257 Context(EnclosingParser->Context) {}
258
259 // Generates an error Message with the bit address prefixed to it.
260 virtual bool Error(const std::string &Message) LLVM_OVERRIDE {
261 uint64_t Bit = Record.GetStartBit() + Context->getHeaderSize() * 8;
262 std::string Buffer;
263 raw_string_ostream StrBuf(Buffer);
264 StrBuf << "(" << format("%"PRIu64":%u", (Bit / 8),
265 static_cast<unsigned>(Bit % 8))
266 << ") " << Message;
267 return Context->Error(StrBuf.str());
268 }
269
270 // Default implementation. Reports that block is unknown and skips
271 // its contents.
272 virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
273
274 // Default implementation. Reports that the record is not
275 // understood.
276 virtual void ProcessRecord() LLVM_OVERRIDE;
277
278 /// Checks if the size of the record is Size. If not, an error is
279 /// produced using the given RecordName. Return true if error was
280 /// reported. Otherwise false.
281 bool checkRecordSize(unsigned Size, const char *RecordName) {
282 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
283 if (Values.size() != Size) {
284 return RecordSizeError(Size, RecordName, 0);
285 }
286 return false;
287 }
288
289 /// Checks if the size of the record is at least as large as the
290 /// LowerLimit.
291 bool checkRecordSizeAtLeast(unsigned LowerLimit, const char *RecordName) {
292 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
293 if (Values.size() < LowerLimit) {
294 return RecordSizeError(LowerLimit, RecordName, "at least");
295 }
296 return false;
297 }
298
299 /// Checks if the size of the record is no larger than the
300 /// UpperLimit.
301 bool checkRecordSizeNoMoreThan(unsigned UpperLimit, const char *RecordName) {
302 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
303 if (Values.size() > UpperLimit) {
304 return RecordSizeError(UpperLimit, RecordName, "no more than");
305 }
306 return false;
307 }
308
309 /// Checks if the size of the record is at least as large as the
310 /// LowerLimit, and no larger than the UpperLimit.
311 bool checkRecordSizeInRange(unsigned LowerLimit, unsigned UpperLimit,
312 const char *RecordName) {
313 return checkRecordSizeAtLeast(LowerLimit, RecordName)
314 || checkRecordSizeNoMoreThan(UpperLimit, RecordName);
315 }
316
317 private:
318
319 /// Generates a record size error. ExpectedSize is the number
320 /// of elements expected. RecordName is the name of the kind of
321 /// record that has incorrect size. ContextMessage (if not 0)
322 /// is appended to "record expects" to describe how ExpectedSize
323 /// should be interpreted.
324 bool RecordSizeError(unsigned ExpectedSize,
325 const char *RecordName,
326 const char *ContextMessage) {
327 std::string Buffer;
328 raw_string_ostream StrBuf(Buffer);
329 StrBuf << RecordName << " record expects";
330 if (ContextMessage) StrBuf << " " << ContextMessage;
331 StrBuf << " " << ExpectedSize << " argument";
332 if(ExpectedSize > 1) StrBuf << "s";
Jim Stichnoth 2014/07/07 20:50:24 if( --> if (
Karl 2014/07/07 21:50:56 Done.
333 StrBuf << ". Found: " << Record.GetValues().size();
334 return Error(StrBuf.str());
335 }
336 };
337
338 bool BlockParserBaseClass::ParseBlock(unsigned BlockID) {
339 // If called, derived class doesn't know how to handle block.
340 // Report error and skip.
341 std::string Buffer;
342 raw_string_ostream StrBuf(Buffer);
343 StrBuf << "Don't know how to parse block id: " << BlockID;
344 Error(StrBuf.str());
345 SkipBlock();
346 return false;
347 }
348
349 void BlockParserBaseClass::ProcessRecord() {
350 // If called, derived class doesn't know how to handle.
351 std::string Buffer;
352 raw_string_ostream StrBuf(Buffer);
353 StrBuf << "Don't know how to process record: " << Record;
354 Error(StrBuf.str());
355 }
356
357 // Class to parse a types block.
358 class TypesParser : public BlockParserBaseClass {
359 public:
360 TypesParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
361 : BlockParserBaseClass(BlockID, EnclosingParser), NextTypeId(0) {}
362
363 ~TypesParser() LLVM_OVERRIDE {}
364
365 private:
366 // The type ID that will be associated with the next type defining
367 // record in the types block.
368 unsigned NextTypeId;
369
370 virtual void ProcessRecord() LLVM_OVERRIDE;
371 };
372
373 void TypesParser::ProcessRecord() {
374 Type *Ty = 0;
Jim Stichnoth 2014/07/07 20:50:23 NULL
Karl 2014/07/07 21:50:56 Done.
375 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
376 switch (Record.GetCode()) {
377 case naclbitc::TYPE_CODE_NUMENTRY:
378 // NUMENTRY: [numentries]
379 if (checkRecordSize(1, "Type count")) return;
380 Context->resizeTypeIDValues(Values[0]);
381 return;
382 case naclbitc::TYPE_CODE_VOID:
383 // VOID
384 if (checkRecordSize(0, "Type void")) break;
385 Ty = Type::getVoidTy(Context->getLLVMContext());
386 break;
387 case naclbitc::TYPE_CODE_FLOAT:
388 // FLOAT
389 if (checkRecordSize(0, "Type float")) break;
390 Ty = Type::getFloatTy(Context->getLLVMContext());
391 break;
392 case naclbitc::TYPE_CODE_DOUBLE:
393 // DOUBLE
394 if (checkRecordSize(0, "Type double")) break;
395 Ty = Type::getDoubleTy(Context->getLLVMContext());
396 break;
397 case naclbitc::TYPE_CODE_INTEGER:
398 // INTEGER: [width]
399 if (checkRecordSize(1, "Type integer")) break;
400 Ty = IntegerType::get(Context->getLLVMContext(), Values[0]);
401 // TODO(kschimpf) Check if size is legal.
402 break;
403 case naclbitc::TYPE_CODE_VECTOR:
404 // VECTOR: [numelts, eltty]
405 if (checkRecordSize(2, "Type vector")) break;
406 Ty = VectorType::get(Context->getTypeByID(Values[1]), Values[0]);
407 break;
408 case naclbitc::TYPE_CODE_FUNCTION: {
409 // FUNCTION: [vararg, retty, paramty x N]
410 if (checkRecordSizeAtLeast(2, "Type signature")) break;
411 SmallVector<Type *, 8> ArgTys;
412 for (unsigned i = 2, e = Values.size(); i != e; ++i) {
413 ArgTys.push_back(Context->getTypeByID(Values[i]));
414 }
415 Ty = FunctionType::get(Context->getTypeByID(Values[1]),
416 ArgTys, Values[0]);
417 break;
418 }
419 default:
420 BlockParserBaseClass::ProcessRecord();
421 break;
422 }
423 // If Ty not defined, assume error. Use void as filler.
424 if (Ty == 0)
Jim Stichnoth 2014/07/07 20:50:24 NULL
Karl 2014/07/07 21:50:56 Done.
425 Ty = Type::getVoidTy(Context->getLLVMContext());
426 Context->setTypeID(NextTypeId++, Ty);
427 }
428
429 /// Parses the globals block (i.e. global variables).
430 class GlobalsParser : public BlockParserBaseClass {
431 public:
432 GlobalsParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
433 : BlockParserBaseClass(BlockID, EnclosingParser),
434 InitializersNeeded(0),
435 Alignment(1),
436 IsConstant(false) {
437 NextGlobalID = Context->getNumFunctionIDs();
438 }
439
440 virtual ~GlobalsParser() LLVM_OVERRIDE {}
441
442 private:
443 // Holds the sequence of initializers for the global.
444 SmallVector<Constant *, 10> Initializers;
445
446 // Keeps track of how many initializers are expected for
447 // the global variable being built.
448 unsigned InitializersNeeded;
449
450 // The alignment assumed for the global variable being built.
451 unsigned Alignment;
452
453 // True if the global variable being built is a constant.
454 bool IsConstant;
455
456 // The index of the next global variable.
457 unsigned NextGlobalID;
458
459 virtual void ExitBlock() LLVM_OVERRIDE {
460 verifyNoMissingInitializers();
461 unsigned NumIDs = Context->getNumGlobalValueIDs();
462 if (NextGlobalID < NumIDs) {
463 unsigned NumFcnIDs = Context->getNumFunctionIDs();
464 std::string Buffer;
465 raw_string_ostream StrBuf(Buffer);
466 StrBuf << "Globals block expects "
467 << (NumIDs - NumFcnIDs)
468 << " global definitions. Found: "
469 << (NextGlobalID - NumFcnIDs);
470 Error(StrBuf.str());
471 }
472 BlockParserBaseClass::ExitBlock();
473 }
474
475 virtual void ProcessRecord() LLVM_OVERRIDE;
476
477 // Checks if the number of initializers needed is the same as the
478 // number found in the bitcode file. If different, and error message
479 // is generated, and the internal state of the parser is fixed so
480 // this condition is no longer violated.
481 void verifyNoMissingInitializers() {
482 if (InitializersNeeded != Initializers.size()) {
483 std::string Buffer;
484 raw_string_ostream StrBuf(Buffer);
485 StrBuf << "Global variable @g"
486 << (NextGlobalID - Context->getNumFunctionIDs())
487 << " expected " << InitializersNeeded << " initializer";
488 if (InitializersNeeded > 1) StrBuf << "s";
489 StrBuf << ". Found: " << Initializers.size();
490 Error(StrBuf.str());
491 // Fix up state so that we can continue.
492 InitializersNeeded = Initializers.size();
493 installGlobalVar();
494 }
495 }
496
497 // Reserves a slot in the list of initializers being built. If there
498 // isn't room for the slot, an error message is generated.
499 void reserveInitializer(const char *RecordName) {
500 if (InitializersNeeded <= Initializers.size()) {
501 Error(std::string(RecordName)
502 + " record: Too many initializers, ignoring.");
503 }
504 }
505
506 // Takes the initializers (and other parser state values) and
507 // installs a global variable (with the initializers) into the list
508 // of ValueIDs.
509 void installGlobalVar() {
510 Constant *Init = 0;
Jim Stichnoth 2014/07/07 20:50:24 NULL
Karl 2014/07/07 21:50:56 Done.
511 switch (Initializers.size()) {
512 case 0:
513 Error("No initializer for global variable in global vars block");
514 return;
515 case 1:
516 Init = Initializers[0];
517 break;
518 default:
519 Init = ConstantStruct::getAnon(Context->getLLVMContext(),
520 Initializers, true);
521 break;
522 }
523 GlobalVariable *GV = new GlobalVariable(
524 *Context->getModule(), Init->getType(), IsConstant,
525 GlobalValue::InternalLinkage, Init, "");
526 GV->setAlignment(Alignment);
527 if (!Context->assignGlobalVariable(GV, NextGlobalID)) {
528 std::string Buffer;
529 raw_string_ostream StrBuf(Buffer);
530 StrBuf << "Defining global V[" << NextGlobalID
531 << "] not allowed. Out of range.";
532 Error(StrBuf.str());
533 }
534 ++NextGlobalID;
535 Initializers.clear();
536 InitializersNeeded = 0;
537 Alignment = 1;
538 IsConstant = false;
539 }
540 };
541
542 void GlobalsParser::ProcessRecord() {
543 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
544 switch (Record.GetCode()) {
545 case naclbitc::GLOBALVAR_COUNT:
546 // COUNT: [n]
547 if (checkRecordSize(1, "Globals count")) return;
548 if (NextGlobalID != Context->getNumFunctionIDs()) {
549 Error("Globals count record not first in block.");
550 return;
551 }
552 verifyNoMissingInitializers();
553 Context->resizeValueIDsForGlobalVarCount(Values[0]);
554 return;
555 case naclbitc::GLOBALVAR_VAR: {
556 // VAR: [align, isconst]
557 if (checkRecordSize(2, "Globals variable")) return;
558 verifyNoMissingInitializers();
559 InitializersNeeded = 1;
560 Initializers.clear();
561 Alignment = (1 << Values[0]) >> 1;
562 IsConstant = Values[1] != 0;
563 return;
564 }
565 case naclbitc::GLOBALVAR_COMPOUND:
566 // COMPOUND: [size]
567 if (checkRecordSize(1, "globals compound")) return;
568 if (Initializers.size() > 0 || InitializersNeeded != 1) {
569 Error("Globals compound record not first initializer");
570 return;
571 }
572 if (Values[0] < 2) {
573 std::string Buffer;
574 raw_string_ostream StrBuf(Buffer);
575 StrBuf << "Globals compound record size invalid. Found: "
576 << Values[0];
577 Error(StrBuf.str());
578 return;
579 }
580 InitializersNeeded = Values[0];
581 return;
582 case naclbitc::GLOBALVAR_ZEROFILL: {
583 // ZEROFILL: [size]
584 if (checkRecordSize(1, "Globals zerofill")) return;
585 reserveInitializer("Globals zerofill");
586 Type *Ty = ArrayType::get(Type::getInt8Ty(Context->getLLVMContext()),
587 Values[0]);
588 Constant *Zero = ConstantAggregateZero::get(Ty);
589 Initializers.push_back(Zero);
590 break;
591 }
592 case naclbitc::GLOBALVAR_DATA: {
593 // DATA: [b0, b1, ...]
594 if (checkRecordSizeAtLeast(1, "Globals data")) return;
595 reserveInitializer("Globals data");
596 unsigned Size = Values.size();
597 SmallVector<uint8_t, 32> Buf;
598 for (unsigned i = 0; i < Size; ++i)
599 Buf.push_back(static_cast<uint8_t>(Values[i]));
600 Constant *Init = ConstantDataArray::get(
601 Context->getLLVMContext(),
602 ArrayRef<uint8_t>(Buf.data(), Buf.size()));
603 Initializers.push_back(Init);
604 break;
605 }
606 case naclbitc::GLOBALVAR_RELOC: {
607 // RELOC: [val, [addend]]
608 if (checkRecordSizeInRange(1, 2, "Globals reloc")) return;
609 Constant *BaseVal =
610 Context->getOrCreateGlobalVarRef(Values[0]);
611 if (BaseVal == 0) {
612 std::string Buffer;
613 raw_string_ostream StrBuf(Buffer);
614 StrBuf << "Can't find global relocation value: " << Values[0];
615 Error(StrBuf.str());
616 return;
617 }
618 Type *IntPtrType = IntegerType::get(Context->getLLVMContext(), 32);
619 Constant *Val = ConstantExpr::getPtrToInt(BaseVal, IntPtrType);
620 if (Values.size() == 2) {
621 Val = ConstantExpr::getAdd(Val, ConstantInt::get(IntPtrType, Values[1]));
622 }
623 Initializers.push_back(Val);
624 break;
625 }
626 default:
627 BlockParserBaseClass::ProcessRecord();
628 return;
629 }
630 // If reached, just processed another initializer. See if time
631 // to install global.
632 if (InitializersNeeded == Initializers.size()) installGlobalVar();
633 }
634
635 // Parses a valuesymtab block in the bitcode file.
636 class ValuesymtabParser : public BlockParserBaseClass {
637 typedef SmallString<128> StringType;
638 public:
639 ValuesymtabParser(unsigned BlockID,
640 BlockParserBaseClass *EnclosingParser,
641 bool AllowBbEntries)
642 : BlockParserBaseClass(BlockID, EnclosingParser),
643 AllowBbEntries(AllowBbEntries) {}
644
645 virtual ~ValuesymtabParser() LLVM_OVERRIDE {}
646
647 private:
648 // True if entries to name basic blocks allowed.
649 bool AllowBbEntries;
650
651 virtual void ProcessRecord() LLVM_OVERRIDE;
652
653 void ConvertToString(StringType &ConvertedName) {
654 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
655 for (size_t i = 1, e = Values.size(); i != e; ++i) {
656 ConvertedName += static_cast<char>(Values[i]);
657 }
658 }
659 };
660
661 void ValuesymtabParser::ProcessRecord() {
662 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
663 StringType ConvertedName;
664 switch (Record.GetCode()) {
665 case naclbitc::VST_CODE_ENTRY: {
666 // VST_ENTRY: [ValueId, namechar x N]
667 if (checkRecordSizeAtLeast(2, "Valuesymtab value entry")) return;
668 ConvertToString(ConvertedName);
669 Value *V = Context->getGlobalValueByID(Values[0]);
670 if (V == 0) {
671 std::string Buffer;
672 raw_string_ostream StrBuf(Buffer);
673 StrBuf << "Invalid global address ID in valuesymtab: " << Values[0];
674 Error(StrBuf.str());
675 return;
676 }
677 V->setName(StringRef(ConvertedName.data(), ConvertedName.size()));
678 return;
679 }
680 case naclbitc::VST_CODE_BBENTRY: {
681 // VST_BBENTRY: [BbId, namechar x N]
682 // For now, since we aren't processing function blocks, don't handle.
683 if (AllowBbEntries) {
684 Error("Valuesymtab bb entry not implemented");
685 return;
686 }
687 break;
688 }
689 default:
690 break;
691 }
692 // If reached, don't know how to handle record.
693 BlockParserBaseClass::ProcessRecord();
694 return;
695 }
696
697 /// Parses the module block in the bitcode file.
698 class ModuleParser : public BlockParserBaseClass {
699 public:
700 ModuleParser(unsigned BlockID, TopLevelParser *Context)
701 : BlockParserBaseClass(BlockID, Context) {}
702
703 virtual ~ModuleParser() LLVM_OVERRIDE {}
704
705 protected:
706 virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
707
708 virtual void ProcessRecord() LLVM_OVERRIDE;
709 };
710
711 bool ModuleParser::ParseBlock(unsigned BlockID) LLVM_OVERRIDE {
712 switch (BlockID) {
713 case naclbitc::BLOCKINFO_BLOCK_ID:
714 return NaClBitcodeParser::ParseBlock(BlockID);
715 case naclbitc::TYPE_BLOCK_ID_NEW: {
716 TypesParser Parser(BlockID, this);
717 return Parser.ParseThisBlock();
718 }
719 case naclbitc::GLOBALVAR_BLOCK_ID: {
720 GlobalsParser Parser(BlockID, this);
721 return Parser.ParseThisBlock();
722 }
723 case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
724 ValuesymtabParser Parser(BlockID, this, false);
725 return Parser.ParseThisBlock();
726 }
727 case naclbitc::FUNCTION_BLOCK_ID: {
728 Error("Function block parser not yet implemented, skipping");
729 SkipBlock();
730 return false;
731 }
732 default:
733 return BlockParserBaseClass::ParseBlock(BlockID);
734 }
735 }
736
737 void ModuleParser::ProcessRecord() {
738 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
739 switch (Record.GetCode()) {
740 case naclbitc::MODULE_CODE_VERSION: {
741 // VERSION: [version#]
742 if (checkRecordSize(1, "Module version")) return;
743 unsigned Version = Values[0];
744 if (Version != 1) {
745 std::string Buffer;
746 raw_string_ostream StrBuf(Buffer);
747 StrBuf << "Unknown bitstream version: " << Version;
748 Error(StrBuf.str());
749 }
750 return;
751 }
752 case naclbitc::MODULE_CODE_FUNCTION: {
753 // FUNCTION: [type, callingconv, isproto, linkage]
754 if (checkRecordSize(4, "Function heading")) return;
755 Type *Ty = Context->getTypeByID(Values[0]);
756 FunctionType *FTy = dyn_cast<FunctionType>(Ty);
757 if (FTy == 0) {
758 std::string Buffer;
759 raw_string_ostream StrBuf(Buffer);
760 StrBuf << "Function heading expects function type. Found: "
761 << Ty;
762 Error(StrBuf.str());
763 return;
764 }
765 CallingConv::ID CallingConv;
766 if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) {
767 std::string Buffer;
768 raw_string_ostream StrBuf(Buffer);
769 StrBuf << "Function heading has unknown calling convention: "
770 << Values[1];
771 Error(StrBuf.str());
772 return;
773 }
774 GlobalValue::LinkageTypes Linkage;
775 if (!naclbitc::DecodeLinkage(Values[3], Linkage)) {
776 std::string Buffer;
777 raw_string_ostream StrBuf(Buffer);
778 StrBuf << "Function heading has unknown linkage. Found "
779 << Values[3];
780 Error(StrBuf.str());
781 return;
782 }
783 Function *Func = Function::Create(FTy, Linkage, "", Context->getModule());
784 Func->setCallingConv(CallingConv);
785 if (Values[2] == 0) Context->setNextValueIDAsImplementedFunction();
786 Context->setNextFunctionID(Func);
787 // TODO(kschimpf) verify if Func matches PNaCl ABI.
788 return;
789 }
790 default:
791 BlockParserBaseClass::ProcessRecord();
792 return;
793 }
794 }
795
796 bool TopLevelParser::ParseBlock(unsigned BlockID) {
797 if (BlockID == naclbitc::MODULE_BLOCK_ID) {
798 ModuleParser Parser(BlockID, this);
799 bool ReturnValue = Parser.ParseThisBlock();
800 // TODO(kschimpf): Remove once translating function blocks.
801 errs() << "Global addresses:\n";
802 for (size_t i = 0; i < ValueIDValues.size(); ++i) {
803 errs() << "[" << i << "]: " << *ValueIDValues[i] << "\n";
804 }
805 return ReturnValue;
806 }
807 // Generate error message by using default block implementation.
808 BlockParserBaseClass Parser(BlockID, this);
809 return Parser.ParseThisBlock();
810 }
811
812 }
jvoung (off chromium) 2014/07/02 22:07:33 // end of anonymous namespace
Karl 2014/07/07 21:50:56 Done.
813
814 namespace Ice {
815
816 void PNaClTranslator::translate(const std::string &IRFilename) {
817 OwningPtr<MemoryBuffer> MemBuf;
818 if (error_code ec =
819 MemoryBuffer::getFileOrSTDIN(IRFilename.c_str(), MemBuf)) {
820 errs() << "Error reading '" << IRFilename << "': "
821 << ec.message() << "\n";
822 ExitStatus = 1;
823 return;
824 }
825
826 if (MemBuf->getBufferSize() % 4 != 0) {
827 errs() << IRFilename
828 << ": Bitcode stream should be a multiple of 4 bytes in length.\n";
829 ExitStatus = 1;
830 return;
831 }
832
833 const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
834 const unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();
835
836 // Read header and verify it is good.
837 NaClBitcodeHeader Header;
838 if (Header.Read(BufPtr, EndBufPtr) || !Header.IsSupported()) {
839 errs() << "Invalid PNaCl bitcode header.\n";
840 ExitStatus = 1;
841 return;
842 }
843
844 // Create a bitstream reader to read the bitcode file.
845 NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr);
846 NaClBitstreamCursor InputStream(InputStreamFile);
847
848 TopLevelParser Parser(MemBuf->getBufferIdentifier(), Header,
849 InputStream, ExitStatus);
850 int TopLevelBlocks = 0;
851 while (!InputStream.AtEndOfStream()) {
852 if (Parser.Parse()) {
853 ExitStatus = 1;
854 return;
855 }
856 ++TopLevelBlocks;
857 }
858
859 if (TopLevelBlocks != 1) {
860 errs() << IRFilename << ": Contains more than one module. Found: "
861 << TopLevelBlocks << "\n";
862 ExitStatus = 1;
863 }
864 return;
865 }
866
867 }
jvoung (off chromium) 2014/07/02 22:07:33 // end of namespace Ice
Karl 2014/07/07 21:50:56 Done.
OLDNEW
« src/PNaClTranslator.h ('K') | « src/PNaClTranslator.h ('k') | src/llvm2ice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698