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

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

Powered by Google App Engine
This is Rietveld 408576698