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

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

Powered by Google App Engine
This is Rietveld 408576698