OLD | NEW |
(Empty) | |
| 1 //===-- NaClObjDump.cpp - Dump PNaCl bitcode contents ---------------------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 |
| 10 #include "llvm/ADT/STLExtras.h" |
| 11 #include "llvm/Analysis/NaCl/PNaClABIProps.h" |
| 12 #include "llvm/Analysis/NaCl/PNaClABITypeChecker.h" |
| 13 #include "llvm/Analysis/NaCl/PNaClAllowedIntrinsics.h" |
| 14 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" |
| 15 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
| 16 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" |
| 17 #include "llvm/Bitcode/NaCl/NaClBitCodes.h" |
| 18 #include "llvm/Bitcode/NaCl/NaClObjDumpStream.h" |
| 19 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| 20 #include "llvm/IR/Constants.h" |
| 21 #include "llvm/IR/DataLayout.h" |
| 22 #include "llvm/IR/InstrTypes.h" |
| 23 #include "llvm/IR/LLVMContext.h" |
| 24 #include "llvm/IR/Module.h" |
| 25 #include "llvm/Support/CommandLine.h" |
| 26 #include "llvm/Support/MemoryBuffer.h" |
| 27 #include "llvm/Support/Format.h" |
| 28 #include "llvm/Support/raw_ostream.h" |
| 29 |
| 30 #include <map> |
| 31 |
| 32 namespace { |
| 33 |
| 34 using namespace llvm; |
| 35 |
| 36 static cl::opt<bool> |
| 37 ReportWarningsAsErrors( |
| 38 "Werror", |
| 39 cl::desc("Report warnings as errors."), |
| 40 cl::init(false)); |
| 41 |
| 42 static cl::opt<bool> |
| 43 IgnorePNaClABIChecks( |
| 44 "ignore-pnaclabi-checks", |
| 45 cl::desc("Ignore checking bitcode for PNaCl ABI violations"), |
| 46 cl::init(false)); |
| 47 |
| 48 /// Class to handle sign rotations in a human readable form. That is, |
| 49 /// the sign is in the low bit. The two special cases are: |
| 50 /// 1) -1 is true for i1. |
| 51 /// 2) The representation allows -0 (which is different than 0). |
| 52 class SignRotatedInt { |
| 53 public: |
| 54 SignRotatedInt(uint64_t Value, Type* ValueType) |
| 55 : SignedValue(Value >> 1), |
| 56 IsNegated((Value & 0x1) |
| 57 && !(ValueType->isIntegerTy() |
| 58 && ValueType->getIntegerBitWidth() == 1)) { |
| 59 } |
| 60 |
| 61 SignRotatedInt() |
| 62 : SignedValue(0), IsNegated(false) {} |
| 63 |
| 64 explicit SignRotatedInt(const SignRotatedInt &V) |
| 65 : SignedValue(V.SignedValue), IsNegated(V.IsNegated) {} |
| 66 |
| 67 void operator=(const SignRotatedInt &V) { |
| 68 SignedValue = V.SignedValue; |
| 69 IsNegated = V.IsNegated; |
| 70 } |
| 71 |
| 72 void Print(raw_ostream &Strm) const { |
| 73 if (IsNegated) Strm << "-"; |
| 74 Strm << SignedValue; |
| 75 } |
| 76 |
| 77 private: |
| 78 int64_t SignedValue; |
| 79 bool IsNegated; |
| 80 }; |
| 81 |
| 82 inline raw_ostream &operator<<(raw_ostream &Strm, const SignRotatedInt &V) { |
| 83 V.Print(Strm); |
| 84 return Strm; |
| 85 } |
| 86 |
| 87 /// Convenience class to be able to print value ids to raw_ostream's. |
| 88 /// Kinds of bitcode Ids: |
| 89 /// a : For abbreviations. |
| 90 /// b : For basic blocks. |
| 91 /// c : For local constants. |
| 92 /// f : For function addresses. |
| 93 /// g : For global variable addresses. |
| 94 /// p : For parameter arguments. |
| 95 /// t : For type values. |
| 96 /// v : For values generated by instructions. |
| 97 class BitcodeId { |
| 98 public: |
| 99 BitcodeId(char Kind, uint32_t Index) |
| 100 : Kind(Kind), Index(Index), IsGlobal(IsGlobalKind(Kind)) { |
| 101 } |
| 102 |
| 103 BitcodeId(const BitcodeId &Id) |
| 104 : Kind(Id.Kind), Index(Id.Index), IsGlobal(Id.IsGlobal) {} |
| 105 |
| 106 BitcodeId(char Kind, uint32_t Index, bool IsGlobal) |
| 107 : Kind(Kind), Index(Index), IsGlobal(IsGlobal) {} |
| 108 |
| 109 void operator=(const BitcodeId &Id) { |
| 110 Kind = Id.Kind; |
| 111 Index = Id.Index; |
| 112 IsGlobal = Id.IsGlobal; |
| 113 } |
| 114 |
| 115 raw_ostream &Print(raw_ostream &Stream) const { |
| 116 return Stream << Prefix() << Kind << Index; |
| 117 } |
| 118 |
| 119 char GetKind() const { |
| 120 return Kind; |
| 121 } |
| 122 |
| 123 std::string GetName() const { |
| 124 std::string Buffer; |
| 125 raw_string_ostream StrBuf(Buffer); |
| 126 Print(StrBuf); |
| 127 return StrBuf.str(); |
| 128 } |
| 129 |
| 130 private: |
| 131 char Kind; |
| 132 uint32_t Index; |
| 133 bool IsGlobal; |
| 134 |
| 135 // Returns true if (default) assumption for kind implies global. |
| 136 static bool IsGlobalKind(char Kind); |
| 137 |
| 138 // Returns the bitcode prefix character that communicates if the |
| 139 // bitcode Id is lcoal or global. |
| 140 char Prefix() const { return IsGlobal ? '@' : '%'; } |
| 141 }; |
| 142 |
| 143 bool BitcodeId::IsGlobalKind(char Kind) { |
| 144 switch (Kind) { |
| 145 case 'f': |
| 146 case 'g': |
| 147 case 't': |
| 148 return true; |
| 149 case 'b': |
| 150 case 'c': |
| 151 case 'p': |
| 152 case 'v': |
| 153 return false; |
| 154 default: |
| 155 errs() << "Bad bitcode id, can't determine (statically) if global: " |
| 156 << Kind << "\n"; |
| 157 report_fatal_error("Unable to continue"); |
| 158 } |
| 159 } |
| 160 |
| 161 raw_ostream &operator<<(raw_ostream &Stream, const BitcodeId &Id) { |
| 162 return Id.Print(Stream); |
| 163 } |
| 164 |
| 165 class NaClDisBlockParser; |
| 166 |
| 167 /// The text formatter for PNaClAsm instructions. |
| 168 class AssemblyTextFormatter : public naclbitc::TextFormatter { |
| 169 public: |
| 170 // Special directive to tokenize type expressions. Used to convert |
| 171 // type signatures into a sequence of tokens. |
| 172 class TypeDirective : public naclbitc::TextFormatter::Directive { |
| 173 public: |
| 174 TypeDirective(TextFormatter *Formatter) |
| 175 : naclbitc::TextFormatter::Directive(Formatter), |
| 176 Typ(0), |
| 177 FcnId(0), |
| 178 AddParams(false) {} |
| 179 |
| 180 ~TypeDirective() override {} |
| 181 |
| 182 private: |
| 183 /// Calls the corresponding method in AssemblyTextFormatter, with |
| 184 /// the locally stored arguments. |
| 185 void MyApply(bool Replay) const override; |
| 186 |
| 187 void MaybeSaveForReplay() const override {} |
| 188 |
| 189 // The type to tokenize. |
| 190 Type *Typ; |
| 191 // Pointer to function id, if not NULL. |
| 192 BitcodeId *FcnId; |
| 193 // true if parameter id's should be added to function signature. |
| 194 bool AddParams; |
| 195 |
| 196 friend class AssemblyTextFormatter; |
| 197 |
| 198 // Internal routine to allow AssemblyTextFormatter::AllocateTypeDirective |
| 199 // to initialize a type directive. |
| 200 void Init(Type *NewTyp, BitcodeId *NewFcnId, bool NewAddParams) { |
| 201 Typ = NewTyp; |
| 202 FcnId = NewFcnId; |
| 203 AddParams = NewAddParams; |
| 204 } |
| 205 }; |
| 206 |
| 207 // Special directive to tokenize an abbreviation. Used to convert |
| 208 // an abbreviation (pointer) into a sequence of tokens. |
| 209 class AbbreviationDirective : public naclbitc::TextFormatter::Directive { |
| 210 public: |
| 211 AbbreviationDirective(TextFormatter *Formatter) |
| 212 : naclbitc::TextFormatter::Directive(Formatter), |
| 213 Abbrev(0) {} |
| 214 |
| 215 ~AbbreviationDirective() override {} |
| 216 |
| 217 private: |
| 218 void MyApply(bool Replay) const override; |
| 219 |
| 220 void MaybeSaveForReplay() const override {} |
| 221 |
| 222 // The abbreviation to tokenize. |
| 223 NaClBitCodeAbbrev *Abbrev; |
| 224 |
| 225 friend class AssemblyTextFormatter; |
| 226 }; |
| 227 |
| 228 // Special directive to tokenize an abbreviation index, if the corresponding |
| 229 // record in the block parser used a user-defined abbreviation. |
| 230 class AbbrevIndexDirective : public naclbitc::TextFormatter::Directive { |
| 231 public: |
| 232 AbbrevIndexDirective(TextFormatter *Formatter) |
| 233 : naclbitc::TextFormatter::Directive(Formatter), |
| 234 Record(0), NumGlobalAbbreviations(0) {} |
| 235 |
| 236 ~AbbrevIndexDirective() override {} |
| 237 |
| 238 private: |
| 239 void MyApply(bool Replay) const override; |
| 240 |
| 241 void MaybeSaveForReplay() const override {} |
| 242 |
| 243 // The record containing the associated abbreviation. |
| 244 NaClBitcodeRecord *Record; |
| 245 |
| 246 // The number of global abbreviations defined for the block the |
| 247 // record appears in. |
| 248 unsigned NumGlobalAbbreviations; |
| 249 |
| 250 friend class AssemblyTextFormatter; |
| 251 }; |
| 252 |
| 253 public: |
| 254 |
| 255 /// Creates an assembly text formatter for the given dump stream. |
| 256 AssemblyTextFormatter(naclbitc::ObjDumpStream &ObjDump) |
| 257 : TextFormatter(ObjDump.Assembly(), |
| 258 std::max(20U, GetAssemblyWidth(ObjDump)), |
| 259 " "), |
| 260 Comma(this, ","), |
| 261 Semicolon(this, ";"), |
| 262 Colon(this, ":"), |
| 263 Space(this), |
| 264 OpenParen(this, "("), |
| 265 CloseParen(this, ")"), |
| 266 OpenAngle(this, "<"), |
| 267 CloseAngle(this, ">"), |
| 268 OpenCurly(this, "{"), |
| 269 CloseCurly(this, "}"), |
| 270 OpenSquare(this, "["), |
| 271 CloseSquare(this, "]"), |
| 272 Endline(this), |
| 273 StartCluster(this), |
| 274 FinishCluster(this) |
| 275 { |
| 276 ContinuationIndent = GetIndent(2); |
| 277 } |
| 278 |
| 279 ~AssemblyTextFormatter() override {} |
| 280 |
| 281 naclbitc::TokenTextDirective Comma; |
| 282 naclbitc::TokenTextDirective Semicolon; |
| 283 naclbitc::TokenTextDirective Colon; |
| 284 naclbitc::SpaceTextDirective Space; |
| 285 naclbitc::OpenTextDirective OpenParen; |
| 286 naclbitc::CloseTextDirective CloseParen; |
| 287 naclbitc::OpenTextDirective OpenAngle; |
| 288 naclbitc::CloseTextDirective CloseAngle; |
| 289 naclbitc::OpenTextDirective OpenCurly; |
| 290 naclbitc::CloseTextDirective CloseCurly; |
| 291 naclbitc::OpenTextDirective OpenSquare; |
| 292 naclbitc::CloseTextDirective CloseSquare; |
| 293 naclbitc::EndlineTextDirective Endline; |
| 294 naclbitc::StartClusteringDirective StartCluster; |
| 295 naclbitc::FinishClusteringDirective FinishCluster; |
| 296 |
| 297 /// Prints the given type as a sequence of tokens. |
| 298 TypeDirective &TokenizeType(Type *Typ) { |
| 299 return AllocateTypeDirective(Typ, 0, false); |
| 300 } |
| 301 |
| 302 /// Prints the named function type as a sequence of tokens. |
| 303 /// Typ is the type signature of the function, and FunctionName |
| 304 /// points to the name of the function. |
| 305 TypeDirective &TokenizeFunctionType(FunctionType *Typ, |
| 306 BitcodeId *FunctionName) { |
| 307 return AllocateTypeDirective(Typ, FunctionName, false); |
| 308 } |
| 309 |
| 310 /// Prints the function signature of the function type. Typ is |
| 311 /// the type signature of the function. FunctionName points to the |
| 312 /// name of the function. Note: Unlike TokenizeFunctionType, this |
| 313 /// method also adds the parameter names to paramter argumements. |
| 314 TypeDirective &TokenizeFunctionSignature(FunctionType *Typ, |
| 315 BitcodeId *FunctionName) { |
| 316 return AllocateTypeDirective(Typ, FunctionName, true); |
| 317 } |
| 318 |
| 319 /// Prints out the abbreviation defined by Abbrev. |
| 320 AbbreviationDirective &TokenizeAbbreviation(NaClBitCodeAbbrev *Abbrev) { |
| 321 AbbreviationDirective *Dir = AbbrevDirMemoryPool.Allocate(this); |
| 322 Dir->Abbrev = Abbrev; |
| 323 return *Dir; |
| 324 } |
| 325 |
| 326 /// If the record was read using a user-defined abbreviation, |
| 327 /// generates assembly tokens describing the abbreviation index |
| 328 /// used. Otherwise, no tokens are generated. NumGlobalAbbreviations |
| 329 /// is used to determine if the user-defined abbreviation is local |
| 330 /// or global. |
| 331 AbbrevIndexDirective &TokenizeAbbrevIndex(NaClBitcodeRecord &Record, |
| 332 unsigned NumGlobalAbbreviations) { |
| 333 AbbrevIndexDirective *Dir = AbbrevIndexDirMemoryPool.Allocate(this); |
| 334 Dir->Record = &Record; |
| 335 Dir->NumGlobalAbbreviations = NumGlobalAbbreviations; |
| 336 return *Dir; |
| 337 } |
| 338 |
| 339 private: |
| 340 // Converts the given type to tokens, based on the values passed in |
| 341 // by TokenizeType, TokenizeFunctionType, or TokenizeFunctionSignature. |
| 342 void TokenizeTypeInternal(Type *Typ, BitcodeId* FcnName, bool AddParams); |
| 343 |
| 344 // The free list of type directives. |
| 345 naclbitc::DirectiveMemoryPool<TypeDirective> TypeDirMemoryPool; |
| 346 |
| 347 // Allocates an instance of TypeDirective with the following fields. |
| 348 TypeDirective &AllocateTypeDirective(Type *Typ, BitcodeId *FcnId, |
| 349 bool AddParams); |
| 350 |
| 351 // Converts the given abbreviation to tokens. |
| 352 void TokenizeAbbreviationInternal(const NaClBitCodeAbbrev *Abbrev); |
| 353 |
| 354 // Helper function that prints out the abbreviation expression |
| 355 // located at Index in the given abbreviation. Updates Index to |
| 356 // next expression in the abbreviation. |
| 357 void TokenizeAbbrevExpression(const NaClBitCodeAbbrev *Abbrev, |
| 358 unsigned &Index); |
| 359 |
| 360 // Prints out the given abbreviation operator. |
| 361 void TokenizeAbbrevOp(const NaClBitCodeAbbrevOp &Op); |
| 362 |
| 363 // The free list for abbreviation directives. |
| 364 naclbitc::DirectiveMemoryPool<AbbreviationDirective> AbbrevDirMemoryPool; |
| 365 |
| 366 // The free list for abbreviation index directives. |
| 367 naclbitc::DirectiveMemoryPool<AbbrevIndexDirective> AbbrevIndexDirMemoryPool; |
| 368 |
| 369 // Computes how wide the assembly portion of the dump file should be. |
| 370 static unsigned GetAssemblyWidth(naclbitc::ObjDumpStream &ObjDump) { |
| 371 int Diff = 80 - (ObjDump.GetRecordWidth()+1); |
| 372 // Make sure there is enough room to print out assembly. |
| 373 return Diff < 20 ? 20 : Diff; |
| 374 } |
| 375 }; |
| 376 |
| 377 void AssemblyTextFormatter::TypeDirective::MyApply(bool Replay) const { |
| 378 assert(!Replay && "Shouldn't have been saved for replay"); |
| 379 AssemblyTextFormatter *AssemblyFormatter = |
| 380 reinterpret_cast<AssemblyTextFormatter*>(Formatter); |
| 381 AssemblyFormatter->TokenizeTypeInternal(Typ, FcnId, AddParams); |
| 382 AssemblyFormatter->TypeDirMemoryPool.Free(const_cast<TypeDirective*>(this)); |
| 383 } |
| 384 |
| 385 void AssemblyTextFormatter::AbbreviationDirective::MyApply(bool Replay) const { |
| 386 assert(!Replay && "Shouldn't have been saved for replay"); |
| 387 AssemblyTextFormatter *AssemblyFormatter = |
| 388 reinterpret_cast<AssemblyTextFormatter*>(Formatter); |
| 389 AssemblyFormatter->TokenizeAbbreviationInternal(Abbrev); |
| 390 AssemblyFormatter->AbbrevDirMemoryPool.Free( |
| 391 const_cast<AbbreviationDirective*>(this)); |
| 392 } |
| 393 |
| 394 AssemblyTextFormatter::TypeDirective &AssemblyTextFormatter:: |
| 395 AllocateTypeDirective(Type *Typ, BitcodeId *FcnId, bool AddParams) { |
| 396 TypeDirective *Element = TypeDirMemoryPool.Allocate(this); |
| 397 Element->Init(Typ, FcnId, AddParams); |
| 398 return *Element; |
| 399 } |
| 400 |
| 401 void AssemblyTextFormatter::TokenizeTypeInternal( |
| 402 Type *Typ, BitcodeId* FcnName, bool AddParams) { |
| 403 switch (Typ->getTypeID()) { |
| 404 case Type::VoidTyID: |
| 405 TextStream << "void"; |
| 406 break; |
| 407 case Type::FloatTyID: |
| 408 TextStream << "float"; |
| 409 break; |
| 410 case Type::DoubleTyID: |
| 411 TextStream << "double"; |
| 412 break; |
| 413 case Type::IntegerTyID: |
| 414 TextStream << "i" << Typ->getIntegerBitWidth(); |
| 415 break; |
| 416 case Type::VectorTyID: { |
| 417 VectorType *VecType = cast<VectorType>(Typ); |
| 418 TextStream << StartCluster << OpenAngle << VecType->getNumElements() |
| 419 << Space << "x" << Space |
| 420 << TokenizeType(VecType->getElementType()) |
| 421 << CloseAngle << FinishCluster; |
| 422 break; |
| 423 } |
| 424 case Type::FunctionTyID: { |
| 425 FunctionType *FcnType = cast<FunctionType>(Typ); |
| 426 unsigned NumParams = FcnType->getFunctionNumParams(); |
| 427 TextStream << StartCluster |
| 428 << TokenizeType(FcnType->getReturnType()) |
| 429 << Space |
| 430 << StartCluster; |
| 431 if (NumParams > 0) TextStream << StartCluster; |
| 432 if (FcnName) TextStream << *FcnName; |
| 433 TextStream << OpenParen << FinishCluster; |
| 434 bool HasParamStartCluster = false; |
| 435 for (unsigned i = 0, NumParams = FcnType->getFunctionNumParams(); |
| 436 i < NumParams; ++i) { |
| 437 if (i > 0) { |
| 438 TextStream << Comma << FinishCluster << Space; |
| 439 HasParamStartCluster = false; |
| 440 } |
| 441 TextStream << StartCluster |
| 442 << TokenizeType(FcnType->getFunctionParamType(i)); |
| 443 if (AddParams) TextStream << Space << BitcodeId('p', i); |
| 444 HasParamStartCluster = true; |
| 445 } |
| 446 if (FcnType->isFunctionVarArg()) { |
| 447 if (HasParamStartCluster) { |
| 448 TextStream << Comma << FinishCluster << Space; |
| 449 } |
| 450 TextStream << StartCluster << "..."; |
| 451 HasParamStartCluster = true; |
| 452 } |
| 453 if (HasParamStartCluster) TextStream << FinishCluster; |
| 454 TextStream << CloseParen << FinishCluster; |
| 455 if (NumParams > 0) TextStream << FinishCluster; |
| 456 break; |
| 457 } |
| 458 default: |
| 459 report_fatal_error("Unsupported PNaCl type found"); |
| 460 break; |
| 461 } |
| 462 } |
| 463 |
| 464 void AssemblyTextFormatter::TokenizeAbbrevOp(const NaClBitCodeAbbrevOp &Op) { |
| 465 // Note: Mimics NaClBitCodeAbbrevOp::Print in NaClBitCodes.cpp |
| 466 switch (Op.getEncoding()) { |
| 467 case NaClBitCodeAbbrevOp::Literal: |
| 468 Tokens() << Op.getValue(); |
| 469 return; |
| 470 case NaClBitCodeAbbrevOp::Fixed: |
| 471 Tokens() << StartCluster << "fixed" << OpenParen << Op.getValue() |
| 472 << CloseParen << FinishCluster; |
| 473 return; |
| 474 case NaClBitCodeAbbrevOp::VBR: |
| 475 Tokens() << StartCluster << "vbr" << OpenParen << Op.getValue() |
| 476 << CloseParen << FinishCluster; |
| 477 return; |
| 478 case NaClBitCodeAbbrevOp::Array: |
| 479 Tokens() << "array"; |
| 480 return; |
| 481 case NaClBitCodeAbbrevOp::Char6: |
| 482 Tokens() << "char6"; |
| 483 return; |
| 484 } |
| 485 } |
| 486 |
| 487 void AssemblyTextFormatter:: |
| 488 TokenizeAbbrevExpression(const NaClBitCodeAbbrev *Abbrev, unsigned &Index) { |
| 489 // Note: Mimics PrintExpression in NaClBitCodes.cpp |
| 490 const NaClBitCodeAbbrevOp &Op = Abbrev->getOperandInfo(Index); |
| 491 TokenizeAbbrevOp(Op); |
| 492 if (unsigned NumArgs = Op.NumArguments()) { |
| 493 Tokens() << StartCluster << OpenParen; |
| 494 for (unsigned i = 0; i < NumArgs; ++i) { |
| 495 ++Index; |
| 496 if (i > 0) { |
| 497 Tokens() << Comma << FinishCluster << Space << StartCluster; |
| 498 } |
| 499 TokenizeAbbrevExpression(Abbrev, Index); |
| 500 } |
| 501 Tokens() << CloseParen << FinishCluster; |
| 502 } |
| 503 } |
| 504 |
| 505 void AssemblyTextFormatter:: |
| 506 TokenizeAbbreviationInternal(const NaClBitCodeAbbrev *Abbrev) { |
| 507 Tokens() << StartCluster << OpenAngle; |
| 508 for (unsigned i = 0; i < Abbrev->getNumOperandInfos(); ++i) { |
| 509 if (i > 0) { |
| 510 Tokens() << Comma << FinishCluster << Space << StartCluster; |
| 511 } |
| 512 TokenizeAbbrevExpression(Abbrev, i); |
| 513 } |
| 514 Tokens() << CloseAngle << FinishCluster; |
| 515 } |
| 516 |
| 517 void AssemblyTextFormatter::AbbrevIndexDirective::MyApply(bool Replay) const { |
| 518 assert(!Replay && "Shouldn't have been saved for replay"); |
| 519 if (!Record->UsedAnAbbreviation()) return; |
| 520 unsigned Index = Record->GetAbbreviationIndex(); |
| 521 if (Index < naclbitc::FIRST_APPLICATION_ABBREV) return; |
| 522 Index -= naclbitc::FIRST_APPLICATION_ABBREV; |
| 523 bool IsGlobal = Index < NumGlobalAbbreviations; |
| 524 if (!IsGlobal) Index -= NumGlobalAbbreviations; |
| 525 BitcodeId AbbrevIndex('a', Index, IsGlobal); |
| 526 AssemblyTextFormatter *Fmtr = |
| 527 reinterpret_cast<AssemblyTextFormatter*>(Formatter); |
| 528 Tokens() << Fmtr->Space << Fmtr->StartCluster << Fmtr->OpenAngle |
| 529 << AbbrevIndex << Fmtr->CloseAngle << Fmtr->FinishCluster; |
| 530 Fmtr->AbbrevIndexDirMemoryPool.Free(const_cast<AbbrevIndexDirective*>(this)); |
| 531 } |
| 532 |
| 533 // Holds possible alignements for loads/stores etc. Used to extract |
| 534 // expected values. |
| 535 static unsigned NaClPossibleLoadStoreAlignments[] = { |
| 536 1, 2, 4, 8 |
| 537 }; |
| 538 |
| 539 // Finds the expected alignments for the load/store, for type Ty. |
| 540 static void NaClGetExpectedLoadStoreAlignment( |
| 541 const DataLayout &DL, Type *Ty, std::vector<unsigned> &ValidAlignments) { |
| 542 for (size_t i = 0; i < array_lengthof(NaClPossibleLoadStoreAlignments); ++i) { |
| 543 unsigned Alignment = NaClPossibleLoadStoreAlignments[i]; |
| 544 if (PNaClABIProps::isAllowedAlignment(&DL, Alignment, Ty)) { |
| 545 ValidAlignments.push_back(Alignment); |
| 546 } |
| 547 } |
| 548 } |
| 549 |
| 550 /// Top-level class to parse bitcode file and transform to |
| 551 /// corresponding disassembled code. |
| 552 class NaClDisTopLevelParser : public NaClBitcodeParser { |
| 553 NaClDisTopLevelParser(const NaClDisTopLevelParser&) LLVM_DELETED_FUNCTION; |
| 554 void operator=(const NaClDisTopLevelParser&) LLVM_DELETED_FUNCTION; |
| 555 |
| 556 public: |
| 557 NaClDisTopLevelParser(NaClBitcodeHeader &Header, |
| 558 const unsigned char *HeaderBuffer, |
| 559 NaClBitstreamCursor &Cursor, |
| 560 naclbitc::ObjDumpStream &ObjDump) |
| 561 : NaClBitcodeParser(Cursor), |
| 562 Mod("ObjDump", getGlobalContext()), |
| 563 ObjDump(ObjDump), |
| 564 AbbrevListener(this), |
| 565 DL(&Mod), |
| 566 AllowedIntrinsics(&Mod.getContext()), |
| 567 AssemblyFormatter(ObjDump), |
| 568 Header(Header), |
| 569 HeaderBuffer(HeaderBuffer), |
| 570 NumFunctions(0), |
| 571 NumGlobals(0), |
| 572 ExpectedNumGlobals(0), |
| 573 NumParams(0), |
| 574 NumConstants(0), |
| 575 NumValuedInsts(0), |
| 576 UnknownType(Type::getVoidTy(Mod.getContext())), |
| 577 PointerType(Type::getInt32Ty(Mod.getContext())), |
| 578 ComparisonType(Type::getInt1Ty(Mod.getContext())), |
| 579 NumDefinedFunctions(0) { |
| 580 SetListener(&AbbrevListener); |
| 581 } |
| 582 |
| 583 ~NaClDisTopLevelParser() override { |
| 584 // Be sure to flush any remaining errors. |
| 585 ObjDump.Flush(); |
| 586 } |
| 587 |
| 588 // Returns the number of errors that were sent to the ObjDump. |
| 589 unsigned GetNumErrors() { |
| 590 return ObjDump.GetNumErrors(); |
| 591 } |
| 592 |
| 593 /// Generates an error with the given message. |
| 594 bool Error(const std::string &Message) override { |
| 595 // Use local error routine so that all errors are treated uniformly. |
| 596 ObjDump.Error() << Message << "\n"; |
| 597 return true; |
| 598 } |
| 599 |
| 600 /// Flushes out objdump and then exits with fatal error. |
| 601 void Fatal() { |
| 602 Fatal(""); |
| 603 } |
| 604 |
| 605 /// Flushes out objdump and then exits with fatal error, using |
| 606 /// the given message. |
| 607 void Fatal(const std::string &Message) { |
| 608 ObjDump.Fatal(Message); |
| 609 } |
| 610 |
| 611 /// Parses the top-level module block. |
| 612 bool ParseBlock(unsigned BlockID) override; |
| 613 |
| 614 /// Installs the given type to the next available type index. |
| 615 void InstallType(Type *Ty) { |
| 616 TypeIdType.push_back(Ty); |
| 617 } |
| 618 |
| 619 /// Returns the type associated with the given type index. |
| 620 Type *GetType(uint32_t Index) { |
| 621 if (Index >= TypeIdType.size()) { |
| 622 BitcodeId Id('t', Index); |
| 623 Errors() << "Can't find definition for " << Id << "\n"; |
| 624 // Recover so that additional errors can be found. |
| 625 return UnknownType; |
| 626 } |
| 627 return TypeIdType[Index]; |
| 628 } |
| 629 |
| 630 /// Returns the number of types (currently) defined in the bitcode |
| 631 /// file. |
| 632 uint32_t GetNumTypes() const { |
| 633 return TypeIdType.size(); |
| 634 } |
| 635 |
| 636 /// Returns true if Type represents a (non-zero sized) value. |
| 637 bool isValidValueType(Type *Ty) const { |
| 638 return Ty->isIntegerTy() || Ty->isFloatTy() || Ty->isDoubleTy() |
| 639 || Ty->isVectorTy(); |
| 640 } |
| 641 |
| 642 /// Installs the given type to the next available function index. |
| 643 void InstallFunctionType(FunctionType *Ty, uint64_t BitAddress) { |
| 644 assert(FunctionIdType.size() == NumFunctions); |
| 645 ++NumFunctions; |
| 646 FunctionIdType.push_back(Ty); |
| 647 FunctionIdAddress.push_back(BitAddress); |
| 648 // Let Valuesymtab change this to true if appropriate. |
| 649 FunctionIdIsIntrinsic.push_back(false); |
| 650 } |
| 651 |
| 652 /// Returns the bit address where the function record appeared in |
| 653 /// the bitcode file. Returns 0 if unknown. |
| 654 uint64_t GetFunctionIdAddress(uint32_t Index) { |
| 655 if (Index >= FunctionIdAddress.size()) return 0; |
| 656 return FunctionIdAddress[Index]; |
| 657 } |
| 658 |
| 659 /// Sets the record bit address to the function ID address (if known). |
| 660 void SetRecordAddressToFunctionIdAddress(uint32_t Index) { |
| 661 uint64_t Address = GetFunctionIdAddress(Index); |
| 662 if (Address) |
| 663 ObjDump.SetRecordBitAddress(Address); |
| 664 } |
| 665 |
| 666 //// Returns the type associated with the given function index. |
| 667 FunctionType *GetFunctionType(uint32_t Index) { |
| 668 if (Index >= FunctionIdType.size()) { |
| 669 BitcodeId Id('f', Index); |
| 670 Errors() << "Can't find definition for " << Id << "\n"; |
| 671 Fatal(); |
| 672 } |
| 673 return FunctionIdType[Index]; |
| 674 } |
| 675 |
| 676 /// Marks the function associated with the given Index as intrinsic. |
| 677 void MarkFunctionAsIntrinsic(uint32_t Index) { |
| 678 if (Index >= FunctionIdIsIntrinsic.size()) { |
| 679 BitcodeId Id('f', Index); |
| 680 Errors() << "Can't define " << Id << " as intrinsic, no definition"; |
| 681 } |
| 682 FunctionIdIsIntrinsic[Index] = true; |
| 683 } |
| 684 |
| 685 /// Returns true if the given Index is for a function intrinsic. |
| 686 bool IsFunctionIntrinsic(uint32_t Index) { |
| 687 if (Index >= FunctionIdIsIntrinsic.size()) return false; |
| 688 return FunctionIdIsIntrinsic[Index]; |
| 689 } |
| 690 |
| 691 /// Returns true if the function is an intrinsic function. |
| 692 bool IsIntrinsicAllowed(const std::string &FuncName, |
| 693 const FunctionType *FuncType) { |
| 694 return AllowedIntrinsics.isAllowed(FuncName, FuncType); |
| 695 } |
| 696 |
| 697 /// Returns the type of the Name'd intrinsic, if defined as an |
| 698 /// allowed intrinsic name. Otherwise returns 0. |
| 699 FunctionType *GetIntrinsicType(const std::string &Name) { |
| 700 return AllowedIntrinsics.getIntrinsicType(Name); |
| 701 } |
| 702 |
| 703 /// Returns the number of functions (currently) defined/declared in |
| 704 /// the bitcode file. |
| 705 uint32_t GetNumFunctions() const { |
| 706 return NumFunctions; |
| 707 } |
| 708 |
| 709 /// Installs that the given function index as having a function body |
| 710 /// (i.e. the function address uses the "define" keyword instead of |
| 711 /// the "declare" keyword). |
| 712 void InstallDefinedFunction(uint32_t Index) { |
| 713 DefinedFunctions.push_back(Index); |
| 714 } |
| 715 |
| 716 /// Returns true if there is an Index defined function block. |
| 717 bool HasDefinedFunctionIndex(uint32_t Index) const { |
| 718 return Index < DefinedFunctions.size(); |
| 719 } |
| 720 |
| 721 /// Returns the function index associated with the Index defined |
| 722 /// function block. |
| 723 uint32_t GetDefinedFunctionIndex(uint32_t Index) const { |
| 724 assert(Index < DefinedFunctions.size()); |
| 725 return DefinedFunctions[NumDefinedFunctions]; |
| 726 } |
| 727 |
| 728 /// Returns true if there is a next defined function index. |
| 729 bool HasNextDefinedFunctionIndex() const { |
| 730 return HasDefinedFunctionIndex(NumDefinedFunctions); |
| 731 } |
| 732 |
| 733 /// Returns the function index associated with the next defined function. |
| 734 uint32_t GetNextDefinedFunctionIndex() const { |
| 735 return GetDefinedFunctionIndex(NumDefinedFunctions); |
| 736 } |
| 737 |
| 738 /// Returns true if the given value ID corresponds to a declared (rather |
| 739 /// than defined) function. |
| 740 bool IsDeclaredFunction(uint32_t Index) { |
| 741 if (Index >= NumFunctions) return false; |
| 742 for (size_t i = 0, e = DefinedFunctions.size(); i < e; ++i) { |
| 743 if (DefinedFunctions[i] == Index) return false; |
| 744 } |
| 745 return true; |
| 746 } |
| 747 |
| 748 /// Increments the number of (currently) defined functions in the |
| 749 /// bitcode file by one. |
| 750 void IncNumDefinedFunctions() { |
| 751 ++NumDefinedFunctions; |
| 752 } |
| 753 |
| 754 void IncNumGlobals() { |
| 755 NumGlobals++; |
| 756 } |
| 757 |
| 758 /// Returns the number of globals (currently) defined in the bitcode |
| 759 /// file. |
| 760 uint32_t GetNumGlobals() const { |
| 761 return NumGlobals; |
| 762 } |
| 763 |
| 764 /// Returns the expected number of globals (as defined by the count |
| 765 /// record of the globals block). |
| 766 uint32_t GetExpectedNumGlobals() const { |
| 767 return ExpectedNumGlobals; |
| 768 } |
| 769 |
| 770 /// Sets field ExpectedNumGlobals to the given value. |
| 771 void SetExpectedNumGlobals(uint32_t NewValue) { |
| 772 ExpectedNumGlobals = NewValue; |
| 773 } |
| 774 |
| 775 /// Installs the given type to the next available parameter index. |
| 776 void InstallParamType(Type *Ty) { |
| 777 while (ParamIdType.size() <= NumParams) { |
| 778 ParamIdType.push_back(UnknownType); |
| 779 } |
| 780 ParamIdType[NumParams++] = Ty; |
| 781 } |
| 782 |
| 783 /// Returns the type associated with the given parameter index. |
| 784 Type *GetParamType(uint32_t Index) { |
| 785 if (Index >= ParamIdType.size()) { |
| 786 BitcodeId Id('p', Index); |
| 787 Errors() << "Can't find defintion for " << Id << "\n"; |
| 788 Fatal(); |
| 789 } |
| 790 return ParamIdType[Index]; |
| 791 } |
| 792 |
| 793 /// Returns the number of parameters (currently) defined in the |
| 794 /// enclosing defined function. |
| 795 uint32_t GetNumParams() const { |
| 796 return NumParams; |
| 797 } |
| 798 |
| 799 /// Installs the given type to the next available constant index. |
| 800 void InstallConstantType(Type *Ty) { |
| 801 while (ConstantIdType.size() <= NumConstants) { |
| 802 ConstantIdType.push_back(UnknownType); |
| 803 } |
| 804 ConstantIdType[NumConstants++] = Ty; |
| 805 } |
| 806 |
| 807 /// Returns the type associated with the given constant index. |
| 808 Type *GetConstantType(uint32_t Index) { |
| 809 if (Index >= ConstantIdType.size()) { |
| 810 BitcodeId Id('c', Index); |
| 811 Errors() << "Can't find definition for " << Id << "\n"; |
| 812 Fatal(); |
| 813 } |
| 814 return ConstantIdType[Index]; |
| 815 } |
| 816 |
| 817 /// Returns the number of constants (currently) defined in the |
| 818 /// enclosing defined function. |
| 819 uint32_t GetNumConstants() const { |
| 820 return NumConstants; |
| 821 } |
| 822 |
| 823 /// Installs the given type to the given instruction index. Note: |
| 824 /// Instruction indices are only associated with instructions that |
| 825 /// generate values. |
| 826 void InstallInstType(Type *Ty, uint32_t Index) { |
| 827 while (InstIdType.size() <= Index) { |
| 828 InstIdType.push_back(UnknownType); |
| 829 } |
| 830 if (InstIdType[Index] != UnknownType && Ty != InstIdType[Index]) { |
| 831 Errors() << BitcodeId('v', Index) << " defined with multiple types: " |
| 832 << *Ty << " and " << *InstIdType[Index] << "\n"; |
| 833 } |
| 834 InstIdType[Index] = Ty; |
| 835 } |
| 836 |
| 837 /// Installs the given type to the next available instruction index. |
| 838 void InstallInstType(Type *Ty) { |
| 839 InstallInstType(Ty, NumValuedInsts++); |
| 840 } |
| 841 |
| 842 /// Returns the type associated with the given instruction index. |
| 843 /// Note: Instruction indices are only associated with instructions |
| 844 /// that generate values. |
| 845 Type *GetInstType(uint32_t Index) { |
| 846 if (Index >= InstIdType.size()) { |
| 847 Errors() << "Can't find type for " << BitcodeId('v', Index) << "\n"; |
| 848 return UnknownType; |
| 849 } |
| 850 return InstIdType[Index]; |
| 851 } |
| 852 |
| 853 /// Returns the number of instructions (in the defined function) |
| 854 /// that (currently) generate values. |
| 855 uint32_t GetNumValuedInstructions() const { |
| 856 return NumValuedInsts; |
| 857 } |
| 858 |
| 859 /// Resets index counters local to a defined function. |
| 860 void ResetLocalCounters() { |
| 861 ParamIdType.clear(); |
| 862 NumParams = 0; |
| 863 NumConstants = 0; |
| 864 InstIdType.clear(); |
| 865 NumValuedInsts = 0; |
| 866 } |
| 867 |
| 868 /// Returns the bitcode id associated with the absolute value index |
| 869 BitcodeId GetBitcodeId(uint32_t Index); |
| 870 |
| 871 /// Returns the type associated with the given absolute value index. |
| 872 /// If UnderlyingType is false, function indices always return a |
| 873 /// pointer type. Otherwise, function indices returns the declared |
| 874 /// type of the function index. |
| 875 Type *GetValueType(uint32_t Index, bool UnderlyingType = false); |
| 876 |
| 877 /// Returns a type to use when the type is unknown. |
| 878 Type *GetUnknownType() const { |
| 879 return UnknownType; |
| 880 } |
| 881 |
| 882 /// Returns the type used to represent a pointer. |
| 883 Type *GetPointerType() const { |
| 884 return PointerType; |
| 885 } |
| 886 |
| 887 /// Returns the type used to represent comparison results. |
| 888 Type *GetComparisonType() const { |
| 889 return ComparisonType; |
| 890 } |
| 891 |
| 892 /// Returns the void type. |
| 893 Type *GetVoidType() const { |
| 894 return Type::getVoidTy(getGlobalContext()); |
| 895 } |
| 896 |
| 897 /// Returns the float (32-bit) type. |
| 898 Type *GetFloatType() const { |
| 899 return Type::getFloatTy(getGlobalContext()); |
| 900 } |
| 901 |
| 902 /// Returns the double (64-bit) type. |
| 903 Type *GetDoubleType() const { |
| 904 return Type::getDoubleTy(getGlobalContext()); |
| 905 } |
| 906 |
| 907 /// Returns an integer type of N bits. |
| 908 Type *GetIntegerType(unsigned N) const { |
| 909 return Type::getIntNTy(getGlobalContext(), N); |
| 910 } |
| 911 |
| 912 /// Returns the number of defined global abbreviations (currently) |
| 913 /// for the given block id. |
| 914 unsigned GetNumGlobalAbbreviations(unsigned BlockID) { |
| 915 return GlobalAbbrevsCountMap[BlockID]; |
| 916 } |
| 917 |
| 918 /// Increments the current number of defined global abbreviations. |
| 919 void IncNumGlobalAbbreviations(unsigned BlockID) { |
| 920 ++GlobalAbbrevsCountMap[BlockID]; |
| 921 } |
| 922 |
| 923 /// Verifies the given integer operator has the right type. Returns |
| 924 /// the operator. |
| 925 const char *VerifyIntArithmeticOp(const char *Op, Type *OpTy) { |
| 926 if (!IgnorePNaClABIChecks && |
| 927 !PNaClABITypeChecker::isValidIntArithmeticType(OpTy)) { |
| 928 Errors() << Op << ": Invalid integer arithmetic type: " << *OpTy; |
| 929 } |
| 930 return Op; |
| 931 } |
| 932 |
| 933 // Checks the Alignment for loading/storing a value of type Ty. If |
| 934 // invalid, generates an appropriate error message. |
| 935 void VerifyMemoryAccessAlignment(const char *Op, Type *Ty, |
| 936 unsigned Alignment) { |
| 937 if (IgnorePNaClABIChecks) return; |
| 938 if (!PNaClABIProps::isAllowedAlignment(&DL, Alignment, Ty)) { |
| 939 raw_ostream &Errs = Errors(); |
| 940 std::vector<unsigned> Alignments; |
| 941 NaClGetExpectedLoadStoreAlignment(DL, Ty, Alignments); |
| 942 if (!Alignments.empty()) { |
| 943 Errs << Op << ": Illegal alignment for " << *Ty << ". Expects: "; |
| 944 bool isFirst = true; |
| 945 for (auto Align : Alignments) { |
| 946 if (isFirst) |
| 947 isFirst = false; |
| 948 else |
| 949 Errs << " or "; |
| 950 Errs << Align; |
| 951 } |
| 952 Errs << "\n"; |
| 953 } else { |
| 954 Errs << Op << ": Not allowed for type: " << *Ty << "\n"; |
| 955 } |
| 956 } |
| 957 } |
| 958 |
| 959 // ****************************************************** |
| 960 // The following return the corresponding methods/fields |
| 961 // from the the assembly formatter/objdumper. |
| 962 // ****************************************************** |
| 963 |
| 964 naclbitc::TokenTextDirective &Semicolon() { |
| 965 return AssemblyFormatter.Semicolon; |
| 966 } |
| 967 |
| 968 naclbitc::TokenTextDirective &Colon() { |
| 969 return AssemblyFormatter.Colon; |
| 970 } |
| 971 |
| 972 naclbitc::SpaceTextDirective &Space() { |
| 973 return AssemblyFormatter.Space; |
| 974 } |
| 975 |
| 976 naclbitc::TokenTextDirective &Comma() { |
| 977 return AssemblyFormatter.Comma; |
| 978 } |
| 979 |
| 980 naclbitc::OpenTextDirective &OpenParen() { |
| 981 return AssemblyFormatter.OpenParen; |
| 982 } |
| 983 |
| 984 naclbitc::CloseTextDirective &CloseParen() { |
| 985 return AssemblyFormatter.CloseParen; |
| 986 } |
| 987 |
| 988 naclbitc::OpenTextDirective &OpenAngle() { |
| 989 return AssemblyFormatter.OpenAngle; |
| 990 } |
| 991 |
| 992 naclbitc::CloseTextDirective &CloseAngle() { |
| 993 return AssemblyFormatter.CloseAngle; |
| 994 } |
| 995 |
| 996 naclbitc::OpenTextDirective &OpenCurly() { |
| 997 return AssemblyFormatter.OpenCurly; |
| 998 } |
| 999 |
| 1000 naclbitc::CloseTextDirective &CloseCurly() { |
| 1001 return AssemblyFormatter.CloseCurly; |
| 1002 } |
| 1003 |
| 1004 naclbitc::OpenTextDirective &OpenSquare() { |
| 1005 return AssemblyFormatter.OpenSquare; |
| 1006 } |
| 1007 |
| 1008 naclbitc::CloseTextDirective &CloseSquare() { |
| 1009 return AssemblyFormatter.CloseSquare; |
| 1010 } |
| 1011 |
| 1012 naclbitc::EndlineTextDirective &Endline() { |
| 1013 return AssemblyFormatter.Endline; |
| 1014 } |
| 1015 |
| 1016 naclbitc::StartClusteringDirective &StartCluster() { |
| 1017 return AssemblyFormatter.StartCluster; |
| 1018 } |
| 1019 |
| 1020 naclbitc::FinishClusteringDirective &FinishCluster() { |
| 1021 return AssemblyFormatter.FinishCluster; |
| 1022 } |
| 1023 |
| 1024 raw_ostream &Tokens() { |
| 1025 return AssemblyFormatter.Tokens(); |
| 1026 } |
| 1027 |
| 1028 raw_ostream &Errors() { |
| 1029 return ObjDump.Error(); |
| 1030 } |
| 1031 |
| 1032 raw_ostream &Warnings() { |
| 1033 if (ReportWarningsAsErrors) return Errors(); |
| 1034 return ObjDump.Warning(); |
| 1035 } |
| 1036 |
| 1037 const std::string &GetAssemblyIndent() const { |
| 1038 return AssemblyFormatter.GetIndent(); |
| 1039 } |
| 1040 |
| 1041 unsigned GetAssemblyNumTabs() const { |
| 1042 return AssemblyFormatter.GetNumTabs(); |
| 1043 } |
| 1044 |
| 1045 void IncAssemblyIndent() { |
| 1046 AssemblyFormatter.Inc(); |
| 1047 } |
| 1048 |
| 1049 void DecAssemblyIndent() { |
| 1050 AssemblyFormatter.Dec(); |
| 1051 } |
| 1052 |
| 1053 void IncRecordIndent() { |
| 1054 ObjDump.IncRecordIndent(); |
| 1055 } |
| 1056 |
| 1057 void DecRecordIndent() { |
| 1058 ObjDump.DecRecordIndent(); |
| 1059 } |
| 1060 |
| 1061 void ObjDumpFlush() { |
| 1062 ObjDump.Flush(); |
| 1063 } |
| 1064 |
| 1065 void ObjDumpSetRecordBitAddress(uint64_t Bit) { |
| 1066 ObjDump.SetRecordBitAddress(Bit); |
| 1067 } |
| 1068 |
| 1069 void ObjDumpWrite(uint64_t Bit, |
| 1070 const NaClBitcodeRecordData &Record, |
| 1071 int32_t AbbrevIndex = |
| 1072 naclbitc::ABBREV_INDEX_NOT_SPECIFIED) { |
| 1073 ObjDump.Write(Bit, Record, AbbrevIndex); |
| 1074 } |
| 1075 |
| 1076 void ObjDumpWrite(uint64_t Bit, |
| 1077 const NaClBitcodeRecord &Record) { |
| 1078 ObjDump.Write(Bit, Record.GetRecordData(), Record.GetAbbreviationIndex()); |
| 1079 } |
| 1080 |
| 1081 AssemblyTextFormatter::TypeDirective & |
| 1082 TokenizeType(Type *Typ) { |
| 1083 return AssemblyFormatter.TokenizeType(Typ); |
| 1084 } |
| 1085 |
| 1086 AssemblyTextFormatter::TypeDirective & |
| 1087 TokenizeFunctionType(FunctionType *Type, BitcodeId *FcnId) { |
| 1088 return AssemblyFormatter.TokenizeFunctionType(Type, FcnId); |
| 1089 } |
| 1090 |
| 1091 AssemblyTextFormatter::TypeDirective & |
| 1092 TokenizeFunctionSignature(FunctionType *Typ, BitcodeId *FcnId) { |
| 1093 return AssemblyFormatter.TokenizeFunctionSignature(Typ, FcnId); |
| 1094 } |
| 1095 |
| 1096 AssemblyTextFormatter::AbbreviationDirective & |
| 1097 TokenizeAbbreviation(NaClBitCodeAbbrev *Abbrev) { |
| 1098 return AssemblyFormatter.TokenizeAbbreviation(Abbrev); |
| 1099 } |
| 1100 |
| 1101 AssemblyTextFormatter::AbbrevIndexDirective & |
| 1102 TokenizeAbbrevIndex(NaClBitcodeRecord &Record, |
| 1103 unsigned NumGlobalAbbreviations) { |
| 1104 return AssemblyFormatter.TokenizeAbbrevIndex(Record, |
| 1105 NumGlobalAbbreviations); |
| 1106 } |
| 1107 |
| 1108 private: |
| 1109 // A placeholder module for associating context and data layout. |
| 1110 Module Mod; |
| 1111 // The output stream to generate disassembly into. |
| 1112 naclbitc::ObjDumpStream &ObjDump; |
| 1113 // Listener used to get abbreviations as they are read. |
| 1114 NaClBitcodeParserListener AbbrevListener; |
| 1115 // DataLayout to use. |
| 1116 const DataLayout DL; |
| 1117 // The set of allowed intrinsics. |
| 1118 PNaClAllowedIntrinsics AllowedIntrinsics; |
| 1119 // The formatter to use to format assembly code. |
| 1120 AssemblyTextFormatter AssemblyFormatter; |
| 1121 // The header appearing before the beginning of the input stream. |
| 1122 NaClBitcodeHeader &Header; |
| 1123 // Pointer to the buffer containing the header. |
| 1124 const unsigned char *HeaderBuffer; |
| 1125 // The list of known types (index i defines the type associated with |
| 1126 // type index i). |
| 1127 std::vector<Type*> TypeIdType; |
| 1128 // The list of known function signatures (index i defines the type |
| 1129 // signature associated with function index i). |
| 1130 std::vector<FunctionType*> FunctionIdType; |
| 1131 // boolean flag defining if function id is an intrinsic. |
| 1132 std::vector<bool> FunctionIdIsIntrinsic; |
| 1133 // The list of record bit addresses associated with corresponding |
| 1134 // declaration of function IDs. |
| 1135 std::vector<uint64_t> FunctionIdAddress; |
| 1136 // The number of function indices currently defined. |
| 1137 uint32_t NumFunctions; |
| 1138 // The number of global indices currently defined. |
| 1139 uint32_t NumGlobals; |
| 1140 // The expected number of global indices (i.e. value of count record |
| 1141 // in the globals block). |
| 1142 uint32_t ExpectedNumGlobals; |
| 1143 // The list of known parameter types (index i defines the type |
| 1144 // associated with parameter index i). |
| 1145 std::vector<Type*>ParamIdType; |
| 1146 // The number of parameter indices currently defined. |
| 1147 uint32_t NumParams; |
| 1148 std::vector<Type*>ConstantIdType; |
| 1149 // The number of constant indices currently defined. |
| 1150 uint32_t NumConstants; |
| 1151 // The list of known instruction types (index i defines the type |
| 1152 // associated with valued instruction index i). |
| 1153 std::vector<Type*> InstIdType; |
| 1154 // The number of valued instructions currently defined. |
| 1155 uint32_t NumValuedInsts; |
| 1156 // Models an unknown type. |
| 1157 Type *UnknownType; |
| 1158 // Models the pointer type. |
| 1159 Type *PointerType; |
| 1160 // Models a result of a comparison. |
| 1161 Type *ComparisonType; |
| 1162 // Keeps list of function indicies (in the order found in the bitcode) |
| 1163 // that correspond to defined functions. |
| 1164 std::vector<uint32_t> DefinedFunctions; |
| 1165 // The number of function indices currently known to be defined. |
| 1166 uint32_t NumDefinedFunctions; |
| 1167 // Holds the number of global abbreviations defined for each block. |
| 1168 std::map<unsigned, unsigned> GlobalAbbrevsCountMap; |
| 1169 }; |
| 1170 |
| 1171 BitcodeId NaClDisTopLevelParser::GetBitcodeId(uint32_t Index) { |
| 1172 if (Index < NumFunctions) { |
| 1173 return BitcodeId('f', Index); |
| 1174 } |
| 1175 Index -= NumFunctions; |
| 1176 if (Index < ExpectedNumGlobals) { |
| 1177 return BitcodeId('g', Index); |
| 1178 } |
| 1179 Index -= ExpectedNumGlobals; |
| 1180 if (Index < NumParams) { |
| 1181 return BitcodeId('p', Index); |
| 1182 } |
| 1183 Index -= NumParams; |
| 1184 if (Index < NumConstants) { |
| 1185 return BitcodeId('c', Index); |
| 1186 } |
| 1187 Index -= NumConstants; |
| 1188 return BitcodeId('v', Index); |
| 1189 } |
| 1190 |
| 1191 Type *NaClDisTopLevelParser::GetValueType(uint32_t Index, bool UnderlyingType) { |
| 1192 uint32_t Idx = Index; |
| 1193 if (Idx < NumFunctions) |
| 1194 return UnderlyingType ? GetFunctionType(Idx) : PointerType; |
| 1195 Idx -= NumFunctions; |
| 1196 if (Idx < ExpectedNumGlobals) |
| 1197 return PointerType; |
| 1198 Idx -= ExpectedNumGlobals; |
| 1199 if (Idx < NumParams) |
| 1200 return GetParamType(Idx); |
| 1201 Idx -= NumParams; |
| 1202 if (Idx < NumConstants) |
| 1203 return GetConstantType(Idx); |
| 1204 Idx -= NumConstants; |
| 1205 return GetInstType(Idx); |
| 1206 } |
| 1207 |
| 1208 // Base class of all block parsers for the bitcode file. Handles |
| 1209 // common actions needed by derived blocks. |
| 1210 // |
| 1211 // Note: This class also handles blocks with unknown block ID's. |
| 1212 class NaClDisBlockParser : public NaClBitcodeParser { |
| 1213 protected: |
| 1214 /// Constructor for the top-level block parser. |
| 1215 NaClDisBlockParser(unsigned BlockID, NaClDisTopLevelParser *Context) |
| 1216 : NaClBitcodeParser(BlockID, Context), |
| 1217 Context(Context){ |
| 1218 InitAbbreviations(); |
| 1219 } |
| 1220 |
| 1221 /// Constructor for nested block parsers. |
| 1222 NaClDisBlockParser(unsigned BlockID, NaClDisBlockParser *EnclosingParser) |
| 1223 : NaClBitcodeParser(BlockID, EnclosingParser), |
| 1224 Context(EnclosingParser->Context) { |
| 1225 InitAbbreviations(); |
| 1226 } |
| 1227 |
| 1228 public: |
| 1229 |
| 1230 ~NaClDisBlockParser() override { |
| 1231 // Be sure to flush any remaining errors reported at end of block. |
| 1232 ObjDumpFlush(); |
| 1233 } |
| 1234 |
| 1235 bool ParseBlock(unsigned BlockID) override; |
| 1236 |
| 1237 protected: |
| 1238 void EnterBlock(unsigned NumWords) override; |
| 1239 |
| 1240 void ExitBlock() override; |
| 1241 |
| 1242 void ProcessRecord() override; |
| 1243 |
| 1244 void ProcessAbbreviation(unsigned BlockID, NaClBitCodeAbbrev *Abbrev, |
| 1245 bool IsLocal) override; |
| 1246 |
| 1247 void InitAbbreviations() { |
| 1248 NumGlobalAbbreviations = Context->GetNumGlobalAbbreviations(GetBlockID()); |
| 1249 NumLocalAbbreviations = 0; |
| 1250 } |
| 1251 |
| 1252 // Prints the block header instruction for the block. Called by EnterBlock. |
| 1253 virtual void PrintBlockHeader(); |
| 1254 |
| 1255 // Dumps the corresponding record for a block enter. |
| 1256 void DumpEnterBlockRecord(); |
| 1257 |
| 1258 // Returns the identifier for the next local abbreviation appearing in |
| 1259 // the block. |
| 1260 BitcodeId NextLocalAbbreviationId() { |
| 1261 return BitcodeId('a', NumLocalAbbreviations, false); |
| 1262 } |
| 1263 |
| 1264 AssemblyTextFormatter::AbbrevIndexDirective &TokenizeAbbrevIndex() { |
| 1265 return Context->TokenizeAbbrevIndex(Record, NumGlobalAbbreviations); |
| 1266 } |
| 1267 |
| 1268 // ***************************************************************** |
| 1269 // The following are dispatching methods that call the corresponding |
| 1270 // method on the Context (i.e. NaClDisTopLevelParser). |
| 1271 // ***************************************************************** |
| 1272 |
| 1273 /// Returns a directive to tokenize the given type. |
| 1274 AssemblyTextFormatter::TypeDirective &TokenizeType(Type *Type) { |
| 1275 return Context->TokenizeType(Type); |
| 1276 } |
| 1277 |
| 1278 /// Returns a directive to tokenize the given function type, |
| 1279 /// using the given function id. |
| 1280 AssemblyTextFormatter::TypeDirective |
| 1281 &TokenizeFunctionType(FunctionType *Type, BitcodeId *FcnId) { |
| 1282 return Context->TokenizeFunctionType(Type, FcnId); |
| 1283 } |
| 1284 |
| 1285 /// Returns a directive to tokenize the function signature, given the |
| 1286 /// type of the function signature, and the given function id. |
| 1287 AssemblyTextFormatter::TypeDirective |
| 1288 &TokenizeFunctionSignature(FunctionType *Typ, BitcodeId *FcnId) { |
| 1289 return Context->TokenizeFunctionSignature(Typ, FcnId); |
| 1290 } |
| 1291 |
| 1292 AssemblyTextFormatter::AbbreviationDirective &TokenizeAbbreviation( |
| 1293 NaClBitCodeAbbrev *Abbrev) { |
| 1294 return Context->TokenizeAbbreviation(Abbrev); |
| 1295 } |
| 1296 |
| 1297 naclbitc::TokenTextDirective &Semicolon() { |
| 1298 return Context->Semicolon(); |
| 1299 } |
| 1300 |
| 1301 naclbitc::TokenTextDirective &Colon() { |
| 1302 return Context->Colon(); |
| 1303 } |
| 1304 |
| 1305 naclbitc::SpaceTextDirective &Space() { |
| 1306 return Context->Space(); |
| 1307 } |
| 1308 |
| 1309 naclbitc::TokenTextDirective &Comma() { |
| 1310 return Context->Comma(); |
| 1311 } |
| 1312 |
| 1313 naclbitc::OpenTextDirective &OpenParen() { |
| 1314 return Context->OpenParen(); |
| 1315 } |
| 1316 |
| 1317 |
| 1318 naclbitc::CloseTextDirective &CloseParen() { |
| 1319 return Context->CloseParen(); |
| 1320 } |
| 1321 |
| 1322 naclbitc::OpenTextDirective &OpenAngle() { |
| 1323 return Context->OpenAngle(); |
| 1324 } |
| 1325 |
| 1326 naclbitc::CloseTextDirective &CloseAngle() { |
| 1327 return Context->CloseAngle(); |
| 1328 } |
| 1329 |
| 1330 naclbitc::OpenTextDirective &OpenCurly() { |
| 1331 return Context->OpenCurly(); |
| 1332 } |
| 1333 |
| 1334 naclbitc::CloseTextDirective &CloseCurly() { |
| 1335 return Context->CloseCurly(); |
| 1336 } |
| 1337 |
| 1338 naclbitc::OpenTextDirective &OpenSquare() { |
| 1339 return Context->OpenSquare(); |
| 1340 } |
| 1341 |
| 1342 naclbitc::CloseTextDirective &CloseSquare() { |
| 1343 return Context->CloseSquare(); |
| 1344 } |
| 1345 |
| 1346 naclbitc::EndlineTextDirective &Endline() { |
| 1347 return Context->Endline(); |
| 1348 } |
| 1349 |
| 1350 naclbitc::StartClusteringDirective &StartCluster() { |
| 1351 return Context->StartCluster(); |
| 1352 } |
| 1353 |
| 1354 naclbitc::FinishClusteringDirective &FinishCluster() { |
| 1355 return Context->FinishCluster(); |
| 1356 } |
| 1357 |
| 1358 raw_ostream &Tokens() { |
| 1359 return Context->Tokens(); |
| 1360 } |
| 1361 |
| 1362 raw_ostream &Errors() { |
| 1363 return Context->Errors(); |
| 1364 } |
| 1365 |
| 1366 raw_ostream &Warnings() { |
| 1367 return Context->Warnings(); |
| 1368 } |
| 1369 |
| 1370 void Fatal() { |
| 1371 return Context->Fatal(); |
| 1372 } |
| 1373 |
| 1374 void Fatal(const std::string &Message) { |
| 1375 return Context->Fatal(Message); |
| 1376 } |
| 1377 |
| 1378 const std::string &GetAssemblyIndent() const { |
| 1379 return Context->GetAssemblyIndent(); |
| 1380 } |
| 1381 |
| 1382 unsigned GetAssemblyNumTabs() const { |
| 1383 return Context->GetAssemblyNumTabs(); |
| 1384 } |
| 1385 |
| 1386 void IncAssemblyIndent() { |
| 1387 Context->IncAssemblyIndent(); |
| 1388 } |
| 1389 |
| 1390 void DecAssemblyIndent() { |
| 1391 Context->DecAssemblyIndent(); |
| 1392 } |
| 1393 |
| 1394 void IncRecordIndent() { |
| 1395 Context->IncRecordIndent(); |
| 1396 } |
| 1397 |
| 1398 void DecRecordIndent() { |
| 1399 Context->DecRecordIndent(); |
| 1400 } |
| 1401 |
| 1402 void ObjDumpFlush() { |
| 1403 Context->ObjDumpFlush(); |
| 1404 } |
| 1405 |
| 1406 void ObjDumpWrite(uint64_t Bit, |
| 1407 const NaClBitcodeRecordData &Record, |
| 1408 int32_t AbbrevIndex = |
| 1409 naclbitc::ABBREV_INDEX_NOT_SPECIFIED) { |
| 1410 Context->ObjDumpWrite(Bit, Record, AbbrevIndex); |
| 1411 } |
| 1412 |
| 1413 void ObjDumpWrite(uint64_t Bit, |
| 1414 const NaClBitcodeRecord &Record) { |
| 1415 Context->ObjDumpWrite(Bit, Record); |
| 1416 } |
| 1417 |
| 1418 void ObjDumpSetRecordBitAddress(uint64_t Bit) { |
| 1419 Context->ObjDumpSetRecordBitAddress(Bit); |
| 1420 } |
| 1421 |
| 1422 void InstallType(Type *Ty) { |
| 1423 Context->InstallType(Ty); |
| 1424 } |
| 1425 |
| 1426 Type *GetType(uint32_t Index) { |
| 1427 return Context->GetType(Index); |
| 1428 } |
| 1429 |
| 1430 uint32_t GetNumTypes() const { |
| 1431 return Context->GetNumTypes(); |
| 1432 } |
| 1433 |
| 1434 bool isValidValueType(Type *Ty) const { |
| 1435 return Context->isValidValueType(Ty); |
| 1436 } |
| 1437 |
| 1438 FunctionType *GetFunctionType(uint32_t Index) { |
| 1439 return Context->GetFunctionType(Index); |
| 1440 } |
| 1441 |
| 1442 uint32_t GetNumFunctions() const { |
| 1443 return Context->GetNumFunctions(); |
| 1444 } |
| 1445 |
| 1446 void IncNumGlobals() { |
| 1447 Context->IncNumGlobals(); |
| 1448 } |
| 1449 |
| 1450 uint32_t GetNumGlobals() const { |
| 1451 return Context->GetNumGlobals(); |
| 1452 } |
| 1453 |
| 1454 void InstallFunctionType(FunctionType *Ty) { |
| 1455 return Context->InstallFunctionType(Ty, Record.GetStartBit()); |
| 1456 } |
| 1457 |
| 1458 void InstallDefinedFunction(uint32_t Index) { |
| 1459 Context->InstallDefinedFunction(Index); |
| 1460 } |
| 1461 |
| 1462 BitcodeId GetBitcodeId(uint32_t Id) { |
| 1463 return Context->GetBitcodeId(Id); |
| 1464 } |
| 1465 |
| 1466 void InstallParamType(Type *Ty) { |
| 1467 Context->InstallParamType(Ty); |
| 1468 } |
| 1469 |
| 1470 uint32_t GetNumParams() const { |
| 1471 return Context->GetNumParams(); |
| 1472 } |
| 1473 void InstallConstantType(Type *ConstantType) { |
| 1474 Context->InstallConstantType(ConstantType); |
| 1475 } |
| 1476 |
| 1477 Type *GetConstantType(uint32_t Index) { |
| 1478 return Context->GetConstantType(Index); |
| 1479 } |
| 1480 |
| 1481 uint32_t GetNumConstants() const { |
| 1482 return Context->GetNumConstants(); |
| 1483 } |
| 1484 |
| 1485 void InstallInstType(Type *Ty, uint32_t Index) { |
| 1486 Context->InstallInstType(Ty, Index); |
| 1487 } |
| 1488 |
| 1489 void InstallInstType(Type *Ty) { |
| 1490 Context->InstallInstType(Ty); |
| 1491 } |
| 1492 |
| 1493 uint32_t GetNumValuedInstructions() const { |
| 1494 return Context->GetNumValuedInstructions(); |
| 1495 } |
| 1496 |
| 1497 Type *GetValueType(uint32_t Id, bool UnderlyingType = false) { |
| 1498 return Context->GetValueType(Id, UnderlyingType); |
| 1499 } |
| 1500 |
| 1501 Type *GetFunctionValueType(uint32_t Id) { |
| 1502 return GetValueType(Id, /* UnderlyingType = */ true); |
| 1503 } |
| 1504 |
| 1505 Type *GetUnknownType() const { |
| 1506 return Context->GetUnknownType(); |
| 1507 } |
| 1508 |
| 1509 Type *GetPointerType() const { |
| 1510 return Context->GetPointerType(); |
| 1511 } |
| 1512 |
| 1513 Type *GetComparisonType() const { |
| 1514 return Context->GetComparisonType(); |
| 1515 } |
| 1516 |
| 1517 Type *GetVoidType() const { |
| 1518 return Context->GetVoidType(); |
| 1519 } |
| 1520 |
| 1521 Type *GetFloatType() const { |
| 1522 return Context->GetFloatType(); |
| 1523 } |
| 1524 |
| 1525 Type *GetDoubleType() const { |
| 1526 return Context->GetDoubleType(); |
| 1527 } |
| 1528 |
| 1529 Type *GetIntegerType(unsigned Size) const { |
| 1530 return Context->GetIntegerType(Size); |
| 1531 } |
| 1532 |
| 1533 const char *VerifyIntArithmeticOp(const char *Op, Type *OpTy) { |
| 1534 return Context->VerifyIntArithmeticOp(Op, OpTy); |
| 1535 } |
| 1536 |
| 1537 protected: |
| 1538 // The context parser that contains decoding state. |
| 1539 NaClDisTopLevelParser *Context; |
| 1540 // The number of global abbreviations defined for this block. |
| 1541 unsigned NumGlobalAbbreviations; |
| 1542 // The current number of local abbreviations defined for this block. |
| 1543 unsigned NumLocalAbbreviations; |
| 1544 }; |
| 1545 |
| 1546 bool NaClDisBlockParser::ParseBlock(unsigned BlockId) { |
| 1547 // Only called if we don't know the details about the block. |
| 1548 ObjDumpSetRecordBitAddress(GetBlock().GetStartBit()); |
| 1549 Errors() << "Don't know how to parse block " << BlockId |
| 1550 << ", when in block " << GetBlockID() << "\n"; |
| 1551 NaClDisBlockParser Parser(BlockId, this); |
| 1552 return Parser.ParseThisBlock(); |
| 1553 } |
| 1554 |
| 1555 void NaClDisBlockParser::PrintBlockHeader() { |
| 1556 Errors() << "Unknown block id found: " << GetBlockID() << "\n"; |
| 1557 Tokens() << "unknown" << Space() << OpenCurly() |
| 1558 << Space() << Space() << "// BlockID = " |
| 1559 << GetBlockID() << Endline(); |
| 1560 } |
| 1561 |
| 1562 void NaClDisBlockParser::EnterBlock(unsigned NumWords) { |
| 1563 PrintBlockHeader(); |
| 1564 DumpEnterBlockRecord(); |
| 1565 IncRecordIndent(); |
| 1566 IncAssemblyIndent(); |
| 1567 } |
| 1568 |
| 1569 void NaClDisBlockParser::ExitBlock() { |
| 1570 DecAssemblyIndent(); |
| 1571 DecRecordIndent(); |
| 1572 Tokens() << CloseCurly() << Endline(); |
| 1573 NaClBitcodeRecordData Exit; |
| 1574 Exit.Code = naclbitc::BLK_CODE_EXIT; |
| 1575 ObjDumpWrite(Record.GetStartBit(), Exit, naclbitc::END_BLOCK); |
| 1576 } |
| 1577 |
| 1578 void NaClDisBlockParser::DumpEnterBlockRecord() { |
| 1579 // TODO(kschimpf): Better integrate this with the bitstream reader |
| 1580 // (which currently doesn't build any records). |
| 1581 NaClBitcodeRecordData Enter; |
| 1582 Enter.Code = naclbitc::BLK_CODE_ENTER; |
| 1583 Enter.Values.push_back(GetBlockID()); |
| 1584 Enter.Values.push_back(Record.GetCursor().getAbbrevIDWidth()); |
| 1585 ObjDumpWrite(GetBlock().GetStartBit(), Enter, naclbitc::ENTER_SUBBLOCK); |
| 1586 } |
| 1587 |
| 1588 void NaClDisBlockParser::ProcessAbbreviation(unsigned BlockID, |
| 1589 NaClBitCodeAbbrev *Abbrev, |
| 1590 bool IsLocal) { |
| 1591 Tokens() << NextLocalAbbreviationId() << Space() << "=" << Space() |
| 1592 << "abbrev" << Space() << TokenizeAbbreviation(Abbrev) |
| 1593 << Semicolon() << Endline(); |
| 1594 ++NumLocalAbbreviations; |
| 1595 ObjDumpWrite(Record.GetStartBit(), Record); |
| 1596 } |
| 1597 |
| 1598 void NaClDisBlockParser::ProcessRecord() { |
| 1599 // Note: Only called if block is not understood. Hence, we |
| 1600 // only report the records. |
| 1601 ObjDumpWrite(Record.GetStartBit(), Record); |
| 1602 } |
| 1603 |
| 1604 /// Parses and disassembles the blockinfo block. |
| 1605 class NaClDisBlockInfoParser : public NaClDisBlockParser { |
| 1606 public: |
| 1607 NaClDisBlockInfoParser(unsigned BlockID, |
| 1608 NaClDisBlockParser *EnclosingParser) |
| 1609 : NaClDisBlockParser(BlockID, EnclosingParser) { |
| 1610 } |
| 1611 |
| 1612 ~NaClDisBlockInfoParser() override {} |
| 1613 |
| 1614 private: |
| 1615 void PrintBlockHeader() override; |
| 1616 |
| 1617 void SetBID() override; |
| 1618 |
| 1619 void ProcessAbbreviation(unsigned BlockID, NaClBitCodeAbbrev *Abbrev, |
| 1620 bool IsLocal) override; |
| 1621 |
| 1622 /// Returns the abbreviation id for the next global abbreviation |
| 1623 /// to be defined for the given block id. |
| 1624 BitcodeId NextGlobalAbbreviationId(unsigned BlockID) { |
| 1625 return BitcodeId('a', Context->GetNumGlobalAbbreviations(BlockID), true); |
| 1626 } |
| 1627 }; |
| 1628 |
| 1629 void NaClDisBlockInfoParser::PrintBlockHeader() { |
| 1630 Tokens() << "abbreviations" << Space() << OpenCurly() |
| 1631 << Space() << Space() << "// BlockID = " |
| 1632 << GetBlockID() << Endline(); |
| 1633 } |
| 1634 |
| 1635 void NaClDisBlockInfoParser::SetBID() { |
| 1636 std::string BlockName; |
| 1637 uint64_t BlockID = Record.GetValues()[0]; |
| 1638 switch (BlockID) { |
| 1639 case naclbitc::MODULE_BLOCK_ID: |
| 1640 Tokens() << "module"; |
| 1641 break; |
| 1642 case naclbitc::CONSTANTS_BLOCK_ID: |
| 1643 Tokens() << "constants"; |
| 1644 break; |
| 1645 case naclbitc::FUNCTION_BLOCK_ID: |
| 1646 Tokens() << "function"; |
| 1647 break; |
| 1648 case naclbitc::VALUE_SYMTAB_BLOCK_ID: |
| 1649 Tokens() << "valuesymtab"; |
| 1650 break; |
| 1651 case naclbitc::TYPE_BLOCK_ID_NEW: |
| 1652 Tokens() << "types"; |
| 1653 break; |
| 1654 case naclbitc::GLOBALVAR_BLOCK_ID: |
| 1655 Tokens() << "globals"; |
| 1656 break; |
| 1657 default: |
| 1658 Tokens() << "block" << OpenParen() << BlockID << CloseParen(); |
| 1659 Errors() << "Block id " << BlockID << " not understood.\n"; |
| 1660 break; |
| 1661 } |
| 1662 Tokens() << Colon() << Endline(); |
| 1663 ObjDumpWrite(Record.GetStartBit(), Record); |
| 1664 } |
| 1665 |
| 1666 void NaClDisBlockInfoParser::ProcessAbbreviation(unsigned BlockID, |
| 1667 NaClBitCodeAbbrev *Abbrev, |
| 1668 bool IsLocal) { |
| 1669 IncAssemblyIndent(); |
| 1670 Tokens() << NextGlobalAbbreviationId(BlockID) << Space() << "=" << Space() |
| 1671 << "abbrev" << Space() << TokenizeAbbreviation(Abbrev) |
| 1672 << Semicolon() << Endline(); |
| 1673 Context->IncNumGlobalAbbreviations(BlockID); |
| 1674 DecAssemblyIndent(); |
| 1675 ObjDumpWrite(Record.GetStartBit(), Record); |
| 1676 } |
| 1677 |
| 1678 /// Parses and disassembles the types block. |
| 1679 class NaClDisTypesParser : public NaClDisBlockParser { |
| 1680 public: |
| 1681 NaClDisTypesParser(unsigned BlockID, |
| 1682 NaClDisBlockParser *EnclosingParser) |
| 1683 : NaClDisBlockParser(BlockID, EnclosingParser), |
| 1684 ExpectedNumTypes(0), |
| 1685 IsFirstRecord(true) |
| 1686 { |
| 1687 } |
| 1688 |
| 1689 ~NaClDisTypesParser() override; |
| 1690 |
| 1691 private: |
| 1692 void PrintBlockHeader() override; |
| 1693 |
| 1694 void ProcessRecord() override; |
| 1695 |
| 1696 /// Returns the value id for the next type to be defined. |
| 1697 BitcodeId NextTypeId() { |
| 1698 return BitcodeId('t', GetNumTypes()); |
| 1699 } |
| 1700 |
| 1701 // Installs unknown type as definition of next type. |
| 1702 void InstallUnknownTypeForNextId(); |
| 1703 |
| 1704 |
| 1705 uint32_t ExpectedNumTypes; |
| 1706 bool IsFirstRecord; |
| 1707 }; |
| 1708 |
| 1709 NaClDisTypesParser::~NaClDisTypesParser() { |
| 1710 if (GetNumTypes() != ExpectedNumTypes) { |
| 1711 Errors() << "Expected " << ExpectedNumTypes << " types but found: " |
| 1712 << GetNumTypes() << "\n"; |
| 1713 } |
| 1714 } |
| 1715 |
| 1716 void NaClDisTypesParser::PrintBlockHeader() { |
| 1717 Tokens() << "types" << Space() << OpenCurly() |
| 1718 << Space() << Space() << "// BlockID = " << GetBlockID() |
| 1719 << Endline(); |
| 1720 } |
| 1721 |
| 1722 void NaClDisTypesParser::InstallUnknownTypeForNextId() { |
| 1723 Type *UnknownType = GetUnknownType(); |
| 1724 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1725 << TokenizeType(UnknownType) << Semicolon() |
| 1726 << TokenizeAbbrevIndex() << Endline(); |
| 1727 InstallType(UnknownType); |
| 1728 } |
| 1729 |
| 1730 void NaClDisTypesParser::ProcessRecord() { |
| 1731 ObjDumpSetRecordBitAddress(Record.GetStartBit()); |
| 1732 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
| 1733 switch (Record.GetCode()) { |
| 1734 case naclbitc::TYPE_CODE_NUMENTRY: { |
| 1735 // NUMENTRY: [numentries] |
| 1736 uint64_t Size = 0; |
| 1737 if (Values.size() == 1) { |
| 1738 Size = Values[0]; |
| 1739 } else { |
| 1740 Errors() << "Count record should have 1 argument. Found: " |
| 1741 << Values.size() << "\n"; |
| 1742 } |
| 1743 if (!IsFirstRecord) { |
| 1744 Errors() << "Count record not first record of types block\n"; |
| 1745 } |
| 1746 Tokens() << "count" << Space() << Size << Semicolon() |
| 1747 << TokenizeAbbrevIndex() << Endline(); |
| 1748 ExpectedNumTypes = Size; |
| 1749 break; |
| 1750 } |
| 1751 case naclbitc::TYPE_CODE_VOID: { |
| 1752 // VOID |
| 1753 if (!Values.empty()) |
| 1754 Errors() << "Void record shouldn't have arguments. Found: " |
| 1755 << Values.size() << "\n"; |
| 1756 Type *VoidType = GetVoidType(); |
| 1757 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1758 << TokenizeType(VoidType) << Semicolon() |
| 1759 << TokenizeAbbrevIndex() << Endline(); |
| 1760 InstallType(VoidType); |
| 1761 break; |
| 1762 } |
| 1763 case naclbitc::TYPE_CODE_FLOAT: { |
| 1764 // FLOAT |
| 1765 if (!Values.empty()) |
| 1766 Errors() << "Float record shoudn't have arguments. Found: " |
| 1767 << Values.size() << "\n"; |
| 1768 Type *FloatType = GetFloatType(); |
| 1769 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1770 << TokenizeType(FloatType) << Semicolon() |
| 1771 << TokenizeAbbrevIndex() << Endline(); |
| 1772 InstallType(FloatType); |
| 1773 break; |
| 1774 } |
| 1775 case naclbitc::TYPE_CODE_DOUBLE: { |
| 1776 // DOUBLE |
| 1777 if (!Values.empty()) |
| 1778 Errors() << "Double record shound't have arguments. Found: " |
| 1779 << Values.size() << "\n"; |
| 1780 Type *DoubleType = GetDoubleType(); |
| 1781 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1782 << TokenizeType(DoubleType) << Semicolon() |
| 1783 << TokenizeAbbrevIndex() << Endline(); |
| 1784 InstallType(DoubleType); |
| 1785 break; |
| 1786 } |
| 1787 case naclbitc::TYPE_CODE_INTEGER: { |
| 1788 // INTEGER: [width] |
| 1789 uint64_t Size; |
| 1790 if (Values.size() == 1) { |
| 1791 Size = Values[0]; |
| 1792 } else { |
| 1793 Errors() << "Integer record should have one argument. Found: " |
| 1794 << Values.size() << "\n"; |
| 1795 Size = 32; |
| 1796 } |
| 1797 switch (Size) { |
| 1798 case 1: |
| 1799 case 8: |
| 1800 case 16: |
| 1801 case 32: |
| 1802 case 64: { |
| 1803 break; |
| 1804 } |
| 1805 default: |
| 1806 if (!IgnorePNaClABIChecks) { |
| 1807 Errors() << "Integer record contains bad integer size: " |
| 1808 << Size << "\n"; |
| 1809 Size = 32; |
| 1810 } |
| 1811 break; |
| 1812 } |
| 1813 Type *IntType = GetIntegerType(Size); |
| 1814 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1815 << TokenizeType(IntType) << Semicolon() |
| 1816 << TokenizeAbbrevIndex() << Endline(); |
| 1817 InstallType(IntType); |
| 1818 break; |
| 1819 } |
| 1820 case naclbitc::TYPE_CODE_VECTOR: { |
| 1821 // VECTOR: [numelts, eltty] |
| 1822 if (Values.size() != 2) { |
| 1823 Errors() << "Vector record should contain two arguments. Found: " |
| 1824 << Values.size() << "\n"; |
| 1825 InstallUnknownTypeForNextId(); |
| 1826 break; |
| 1827 } |
| 1828 Type *BaseType = GetType(Values[1]); |
| 1829 if (!(BaseType->isIntegerTy() |
| 1830 || BaseType->isFloatTy() |
| 1831 || BaseType->isDoubleTy())) { |
| 1832 Type *ErrorRecoveryTy = GetIntegerType(32); |
| 1833 Errors() << "Vectors can only be defined on primitive types. Found " |
| 1834 << *BaseType << ". Assuming " << *ErrorRecoveryTy |
| 1835 << " instead.\n"; |
| 1836 BaseType = ErrorRecoveryTy; |
| 1837 } |
| 1838 uint64_t NumElements = Values[0]; |
| 1839 Type *VecType = VectorType::get(BaseType, NumElements); |
| 1840 if (!IgnorePNaClABIChecks && |
| 1841 !PNaClABITypeChecker::isValidVectorType(VecType)) { |
| 1842 Errors() << "Vector type " << *VecType << " not allowed.\n"; |
| 1843 } |
| 1844 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1845 << TokenizeType(VecType) << Semicolon() |
| 1846 << TokenizeAbbrevIndex() << Endline(); |
| 1847 InstallType(VecType); |
| 1848 break; |
| 1849 } |
| 1850 case naclbitc::TYPE_CODE_FUNCTION: { |
| 1851 // FUNCTION: [vararg, retty, paramty x N] |
| 1852 if (Values.size() < 2) { |
| 1853 Errors() |
| 1854 << "Function record should contain at least 2 arguments. Found: " |
| 1855 << Values.size() << "\n"; |
| 1856 InstallUnknownTypeForNextId(); |
| 1857 break; |
| 1858 } |
| 1859 if (Values[0]) { |
| 1860 Errors() << "Functions with variable length arguments is not supported\n"; |
| 1861 } |
| 1862 Type *ReturnType = GetType(Values[1]); |
| 1863 if (!(isValidValueType(ReturnType) || ReturnType->isVoidTy())) { |
| 1864 Type *ReplaceType = GetIntegerType(32); |
| 1865 Errors() << "Invalid return type. Found: " << *ReturnType |
| 1866 << ". Assuming: " << *ReplaceType << "\n"; |
| 1867 ReturnType = ReplaceType; |
| 1868 } |
| 1869 SmallVector<Type*, 8> Signature; |
| 1870 for (size_t i = 2; i < Values.size(); ++i) { |
| 1871 Type *Ty = GetType(Values[i]); |
| 1872 if (!isValidValueType(Ty)) { |
| 1873 Type *ReplaceTy = GetIntegerType(32); |
| 1874 Errors() << "Invalid type for parameter " << (i - 1) << ". Found: " |
| 1875 << *Ty << ". Assuming: " << *ReplaceTy << "\n"; |
| 1876 Ty = ReplaceTy; |
| 1877 } |
| 1878 Signature.push_back(Ty); |
| 1879 } |
| 1880 Type *FcnType = FunctionType::get(ReturnType, Signature, Values[0]); |
| 1881 Tokens() << NextTypeId() << Space() << "=" << Space() |
| 1882 << StartCluster() << TokenizeType(FcnType) |
| 1883 << Semicolon() << FinishCluster() << TokenizeAbbrevIndex() |
| 1884 << Endline(); |
| 1885 InstallType(FcnType); |
| 1886 break; |
| 1887 } |
| 1888 default: |
| 1889 Errors() << "Unknown record code in types block. Found: " |
| 1890 << Record.GetCode() << "\n"; |
| 1891 break; |
| 1892 } |
| 1893 ObjDumpWrite(Record.GetStartBit(), Record); |
| 1894 IsFirstRecord = false; |
| 1895 } |
| 1896 |
| 1897 /// Parses and disassembles the globalvars block. |
| 1898 class NaClDisGlobalsParser : public NaClDisBlockParser { |
| 1899 public: |
| 1900 NaClDisGlobalsParser(unsigned BlockID, |
| 1901 NaClDisBlockParser *EnclosingParser) |
| 1902 : NaClDisBlockParser(BlockID, EnclosingParser), |
| 1903 NumInitializers(0), |
| 1904 InsideCompound(false), |
| 1905 BaseTabs(GetAssemblyNumTabs()+1) {} |
| 1906 |
| 1907 ~NaClDisGlobalsParser() override {} |
| 1908 |
| 1909 private: |
| 1910 void PrintBlockHeader() override; |
| 1911 |
| 1912 void ProcessRecord() override; |
| 1913 |
| 1914 void ExitBlock() override; |
| 1915 |
| 1916 // Expected number of initializers associated with last globalvars |
| 1917 // record |
| 1918 uint32_t NumInitializers; |
| 1919 // True if last globalvars record was defined by a compound record. |
| 1920 bool InsideCompound; |
| 1921 // Number of tabs used to indent elements in the globals block. |
| 1922 unsigned BaseTabs; |
| 1923 |
| 1924 // Returns the ID for the next defined global. |
| 1925 BitcodeId NextGlobalId() { |
| 1926 return BitcodeId('g', GetNumGlobals()); |
| 1927 } |
| 1928 |
| 1929 // Prints out the close initializer "}" if necessary, and fixes |
| 1930 // the indentation to match previous indentation. |
| 1931 void InsertCloseInitializer(); |
| 1932 |
| 1933 uint32_t GetExpectedNumGlobals() const { |
| 1934 return Context->GetExpectedNumGlobals(); |
| 1935 } |
| 1936 }; |
| 1937 |
| 1938 void NaClDisGlobalsParser::PrintBlockHeader() { |
| 1939 Tokens() << "globals" << Space() << OpenCurly() |
| 1940 << Space() << Space() << "// BlockID = " << GetBlockID() |
| 1941 << Endline(); |
| 1942 } |
| 1943 |
| 1944 void NaClDisGlobalsParser::InsertCloseInitializer() { |
| 1945 if (InsideCompound) { |
| 1946 while (BaseTabs + 1 < GetAssemblyNumTabs()) DecAssemblyIndent(); |
| 1947 Tokens() << CloseCurly() << Endline(); |
| 1948 } |
| 1949 while (BaseTabs < GetAssemblyNumTabs()) DecAssemblyIndent(); |
| 1950 ObjDumpFlush(); |
| 1951 NumInitializers = 0; |
| 1952 InsideCompound = false; |
| 1953 } |
| 1954 |
| 1955 void NaClDisGlobalsParser::ExitBlock() { |
| 1956 if (NumInitializers > 0) { |
| 1957 BitcodeId LastGlobal('g', (GetNumGlobals()-1)); |
| 1958 Errors() << "More initializers for " << LastGlobal << " expected: " |
| 1959 << NumInitializers << "\n"; |
| 1960 } |
| 1961 if (GetNumGlobals() != GetExpectedNumGlobals()) { |
| 1962 Errors() << "Expected " << GetExpectedNumGlobals() |
| 1963 << " globals but found: " << GetNumGlobals() << "\n"; |
| 1964 } |
| 1965 NaClDisBlockParser::ExitBlock(); |
| 1966 } |
| 1967 |
| 1968 void NaClDisGlobalsParser::ProcessRecord() { |
| 1969 ObjDumpSetRecordBitAddress(Record.GetStartBit()); |
| 1970 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
| 1971 switch (Record.GetCode()) { |
| 1972 case naclbitc::GLOBALVAR_VAR: { |
| 1973 // VAR: [align, isconst] |
| 1974 if (Values.size() != 2) { |
| 1975 Errors() << "Globalvar record expects two arguments. Found: " |
| 1976 << Values.size() << "\n"; |
| 1977 break; |
| 1978 } |
| 1979 if (GetNumGlobals() == GetExpectedNumGlobals()) { |
| 1980 Errors() << "Exceeded expected number of globals: " |
| 1981 << GetExpectedNumGlobals() << "\n"; |
| 1982 } |
| 1983 if (NumInitializers > 0) { |
| 1984 Errors() << "Previous initializer list too short. Expects " |
| 1985 << NumInitializers << " more initializers\n"; |
| 1986 InsertCloseInitializer(); |
| 1987 } |
| 1988 uint32_t Alignment = (1 << Values[0]) >> 1; |
| 1989 Tokens() << StartCluster() << (Values[1] ? "const" : "var") |
| 1990 << Space() << NextGlobalId() |
| 1991 << Comma() << FinishCluster() << Space() |
| 1992 << StartCluster() << "align" << Space() << Alignment |
| 1993 << Comma() << FinishCluster() << TokenizeAbbrevIndex() |
| 1994 << Endline(); |
| 1995 IncAssemblyIndent(); |
| 1996 IncNumGlobals(); |
| 1997 NumInitializers = 1; |
| 1998 break; |
| 1999 } |
| 2000 case naclbitc::GLOBALVAR_COMPOUND: |
| 2001 // COMPOUND: [size] |
| 2002 if (Values.size() != 1) { |
| 2003 Errors() << "Compound record expects one argument. Found: " |
| 2004 << Values.size() << "\n"; |
| 2005 break; |
| 2006 } |
| 2007 if (NumInitializers == 1) { |
| 2008 if (InsideCompound) { |
| 2009 Errors() << "Nested initialization records not allowed\n"; |
| 2010 InsertCloseInitializer(); |
| 2011 } |
| 2012 } else { |
| 2013 Errors() << "Compound record must follow globalvars record\n"; |
| 2014 InsertCloseInitializer(); |
| 2015 } |
| 2016 Tokens() << StartCluster() << "initializers" << Space() |
| 2017 << Values[0] << FinishCluster() << Space() |
| 2018 << OpenCurly() << TokenizeAbbrevIndex() << Endline(); |
| 2019 IncAssemblyIndent(); |
| 2020 NumInitializers = Values[0]; |
| 2021 InsideCompound = true; |
| 2022 break; |
| 2023 case naclbitc::GLOBALVAR_ZEROFILL: |
| 2024 // ZEROFILL: [size] |
| 2025 if (Values.size() != 1) { |
| 2026 Errors() << "Zerofill record expects one argument. Found: " |
| 2027 << Values.size() << "\n"; |
| 2028 break; |
| 2029 } |
| 2030 if (NumInitializers == 0) { |
| 2031 Errors() << "Zerofill initializer not associated with globalvar record\n"; |
| 2032 } |
| 2033 Tokens() << "zerofill" << Space() << Values[0] << Semicolon() |
| 2034 << TokenizeAbbrevIndex() << Endline(); |
| 2035 --NumInitializers; |
| 2036 break; |
| 2037 case naclbitc::GLOBALVAR_DATA: { |
| 2038 // DATA: [b0, b1, ...] |
| 2039 if (Values.empty()) { |
| 2040 Errors() << "Globals data record must have arguments.\n"; |
| 2041 } |
| 2042 if (NumInitializers == 0) { |
| 2043 Errors() << "Data initializer not associated with globalvar record\n"; |
| 2044 } |
| 2045 Tokens() << StartCluster() << OpenCurly(); |
| 2046 for (size_t i = 0; i < Values.size(); ++i) { |
| 2047 if (i > 0) Tokens() << Comma() << FinishCluster() << Space(); |
| 2048 uint64_t Byte = Values[i]; |
| 2049 if (Byte >= 256) { |
| 2050 Errors() << "Invalid byte value in data record: " << Byte << "\n"; |
| 2051 Byte &= 0xFF; |
| 2052 } |
| 2053 if (i > 0) Tokens() << StartCluster(); |
| 2054 Tokens() << format("%3u", static_cast<unsigned>(Byte)); |
| 2055 } |
| 2056 Tokens() << CloseCurly() << FinishCluster() << TokenizeAbbrevIndex() |
| 2057 << Endline(); |
| 2058 --NumInitializers; |
| 2059 break; |
| 2060 } |
| 2061 case naclbitc::GLOBALVAR_RELOC: |
| 2062 // RELOC: [val, [addend]] |
| 2063 if (Values.empty() || Values.size() > 2) { |
| 2064 Errors() << "Invalid reloc record size: " << Values.size() << "\n"; |
| 2065 break; |
| 2066 } |
| 2067 if (NumInitializers == 0) { |
| 2068 Errors() << |
| 2069 "Relocation initializer not associated with globalvar record\n"; |
| 2070 } |
| 2071 Tokens() << "reloc" << Space() << StartCluster() << GetBitcodeId(Values[0]); |
| 2072 if (Values.size() == 2) { |
| 2073 int32_t Addend = static_cast<int32_t>(Values[1]); |
| 2074 char Operator = '+'; |
| 2075 if (Addend < 0) { |
| 2076 Operator = '-'; |
| 2077 Addend = -Addend; |
| 2078 } |
| 2079 Tokens() << Space()<< Operator << Space() << Addend; |
| 2080 } |
| 2081 Tokens() << Semicolon() << FinishCluster() << TokenizeAbbrevIndex() |
| 2082 << Endline(); |
| 2083 --NumInitializers; |
| 2084 break; |
| 2085 case naclbitc::GLOBALVAR_COUNT: { |
| 2086 // COUNT: [n] |
| 2087 uint32_t Count = 0; |
| 2088 if (Values.size() == 1) { |
| 2089 Count = Values[0]; |
| 2090 } else { |
| 2091 Errors() << "Globals count record expects one argument. Found: " |
| 2092 << Values.size() << "\n"; |
| 2093 } |
| 2094 if (GetNumGlobals() != 0) |
| 2095 Errors() << "Count record not first record in block.\n"; |
| 2096 Tokens() << "count" << Space() << Count << Semicolon() |
| 2097 << TokenizeAbbrevIndex() << Endline(); |
| 2098 Context->SetExpectedNumGlobals(Count); |
| 2099 break; |
| 2100 } |
| 2101 default: |
| 2102 Errors() << "Unknown record found in globals block.\n"; |
| 2103 } |
| 2104 |
| 2105 ObjDumpWrite(Record.GetStartBit(), Record); |
| 2106 |
| 2107 if (GetNumGlobals() > 0 && NumInitializers == 0) |
| 2108 InsertCloseInitializer(); |
| 2109 } |
| 2110 |
| 2111 /// Parsers and disassembles a valuesymtab block. |
| 2112 class NaClDisValueSymtabParser : public NaClDisBlockParser { |
| 2113 public: |
| 2114 NaClDisValueSymtabParser(unsigned BlockID, |
| 2115 NaClDisBlockParser *EnclosingParser) |
| 2116 : NaClDisBlockParser(BlockID, EnclosingParser) { |
| 2117 } |
| 2118 |
| 2119 ~NaClDisValueSymtabParser() override {} |
| 2120 |
| 2121 private: |
| 2122 void PrintBlockHeader() override; |
| 2123 |
| 2124 void ProcessRecord() override; |
| 2125 |
| 2126 // Displays the context of the name (in Values) for the given Id. |
| 2127 void DisplayEntry(BitcodeId &Id, |
| 2128 const NaClBitcodeRecord::RecordVector &Values); |
| 2129 }; |
| 2130 |
| 2131 void NaClDisValueSymtabParser::PrintBlockHeader() { |
| 2132 Tokens() << "valuesymtab" << Space() << OpenCurly() |
| 2133 << Space() << Space() << "// BlockID = " << GetBlockID() |
| 2134 << Endline(); |
| 2135 } |
| 2136 |
| 2137 void NaClDisValueSymtabParser:: |
| 2138 DisplayEntry(BitcodeId &Id, |
| 2139 const NaClBitcodeRecord::RecordVector &Values) { |
| 2140 if (Values.size() <= 1) { |
| 2141 Errors() << "Valuesymtab entry record expects 2 arguments. Found: " |
| 2142 << Values.size() << "\n"; |
| 2143 return; |
| 2144 } |
| 2145 Tokens() << Id << Space() << Colon() << Space(); |
| 2146 // Check if the name of the symbol is alphanumeric. If so, print |
| 2147 // as a string. Otherwise, print a sequence of bytes. |
| 2148 // Note: The check isChar6 is a test for aphanumeric + {'.', '_'}. |
| 2149 bool IsChar6 = true; // Until proven otherwise. |
| 2150 for (size_t i = 1; i < Values.size(); ++i) { |
| 2151 uint64_t Byte = Values[i]; |
| 2152 if (Byte >= 256) { |
| 2153 Errors() << "Argument " << i << " of symbol entry not byte: " |
| 2154 << Byte << "\n"; |
| 2155 IsChar6 = false; |
| 2156 break; |
| 2157 } |
| 2158 if (!NaClBitCodeAbbrevOp::isChar6(Byte)) |
| 2159 IsChar6 = false; |
| 2160 } |
| 2161 if (IsChar6) { |
| 2162 Tokens() << StartCluster() << "\""; |
| 2163 for (size_t i = 1; i < Values.size(); ++i) { |
| 2164 Tokens() << static_cast<char>(Values[i]); |
| 2165 } |
| 2166 Tokens() << "\"" << Semicolon(); |
| 2167 } else { |
| 2168 Tokens() << StartCluster() << OpenCurly(); |
| 2169 for (size_t i = 1; i < Values.size(); ++i) { |
| 2170 if (i > 1) { |
| 2171 Tokens() << Comma() << FinishCluster() << Space() |
| 2172 << StartCluster(); |
| 2173 } |
| 2174 char ch = Values[i]; |
| 2175 if (NaClBitCodeAbbrevOp::isChar6(ch)) { |
| 2176 Tokens() << "'" << ch << "'"; |
| 2177 } else { |
| 2178 Tokens() << format("%3u", static_cast<unsigned>(ch)); |
| 2179 } |
| 2180 } |
| 2181 Tokens() << CloseCurly(); |
| 2182 } |
| 2183 Tokens() << FinishCluster() << TokenizeAbbrevIndex() << Endline(); |
| 2184 } |
| 2185 |
| 2186 void NaClDisValueSymtabParser::ProcessRecord() { |
| 2187 ObjDumpSetRecordBitAddress(Record.GetStartBit()); |
| 2188 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
| 2189 switch (Record.GetCode()) { |
| 2190 case naclbitc::VST_CODE_ENTRY: { |
| 2191 // VST_ENTRY: [valueid, namechar x N] |
| 2192 uint32_t ValID = Values[0]; |
| 2193 BitcodeId ID(GetBitcodeId(ValID)); |
| 2194 DisplayEntry(ID, Values); |
| 2195 if (ValID < GetNumFunctions()) { |
| 2196 // Check if value is intrinsic name. If so, verify function signature. |
| 2197 std::string Name; |
| 2198 for (unsigned i = 1; i < Values.size(); ++i) { |
| 2199 Name.push_back(static_cast<char>(Values[i])); |
| 2200 } |
| 2201 FunctionType *IntrinTy = Context->GetIntrinsicType(Name); |
| 2202 if (IntrinTy == 0) |
| 2203 // TODO(kschimpf): Check for _start? Complain about other names? |
| 2204 break; |
| 2205 Context->MarkFunctionAsIntrinsic(ValID); |
| 2206 // Verify that expected intrinsic function type matches declared |
| 2207 // type signature. |
| 2208 FunctionType *FcnTy = GetFunctionType(ValID); |
| 2209 if (FcnTy->getNumParams() != IntrinTy->getNumParams()) { |
| 2210 Errors() << "Intrinsic " << Name |
| 2211 << " expects " << IntrinTy->getNumParams() |
| 2212 << " arguments. Found: " << FcnTy->getNumParams() |
| 2213 << "\n"; |
| 2214 break; |
| 2215 } |
| 2216 if (!IgnorePNaClABIChecks && !PNaClABITypeChecker::IsPointerEquivType( |
| 2217 IntrinTy->getReturnType(), FcnTy->getReturnType())) { |
| 2218 Errors() << "Intrinsic " << Name |
| 2219 << " expects return type " << *IntrinTy->getReturnType() |
| 2220 << ". Found: " << *FcnTy->getReturnType() << "\n"; |
| 2221 break; |
| 2222 } |
| 2223 for (size_t i = 0; i < FcnTy->getNumParams(); ++i) { |
| 2224 if (!IgnorePNaClABIChecks && !PNaClABITypeChecker::IsPointerEquivType( |
| 2225 IntrinTy->getParamType(i), |
| 2226 FcnTy->getParamType(i))) { |
| 2227 Errors() << "Intrinsic " << Name |
| 2228 << " expects " << *IntrinTy->getParamType(i) |
| 2229 << " for argument " << (i+1) << ". Found: " |
| 2230 << *FcnTy->getParamType(i) << "\n"; |
| 2231 break; |
| 2232 } |
| 2233 } |
| 2234 } |
| 2235 break; |
| 2236 } |
| 2237 case naclbitc::VST_CODE_BBENTRY: { |
| 2238 // [bbid, namechar x N] |
| 2239 BitcodeId ID('b', Values[0]); |
| 2240 DisplayEntry(ID, Values); |
| 2241 break; |
| 2242 } |
| 2243 default: |
| 2244 Errors() << "Unknown record in valuesymtab block.\n"; |
| 2245 break; |
| 2246 } |
| 2247 ObjDumpWrite(Record.GetStartBit(), Record); |
| 2248 } |
| 2249 |
| 2250 /// Parses and disassembles a constants block. |
| 2251 class NaClDisConstantsParser : public NaClDisBlockParser { |
| 2252 public: |
| 2253 NaClDisConstantsParser(unsigned BlockID, |
| 2254 NaClDisBlockParser *EnclosingParser) |
| 2255 : NaClDisBlockParser(BlockID, EnclosingParser), |
| 2256 ConstantType(0), |
| 2257 BlockTabs(GetAssemblyNumTabs()) {} |
| 2258 |
| 2259 virtual ~NaClDisConstantsParser() { |
| 2260 while (BlockTabs < GetAssemblyNumTabs()) DecAssemblyIndent(); |
| 2261 } |
| 2262 |
| 2263 private: |
| 2264 void PrintBlockHeader() override; |
| 2265 |
| 2266 void ProcessRecord() override; |
| 2267 |
| 2268 /// Generates the value id for the next generated constant. |
| 2269 BitcodeId NextConstId() { |
| 2270 return BitcodeId('c', GetNumConstants()); |
| 2271 } |
| 2272 |
| 2273 // The type associated with the constant. |
| 2274 Type *ConstantType; |
| 2275 // The number of tabs used to indent the globals block. |
| 2276 unsigned BlockTabs; |
| 2277 }; |
| 2278 |
| 2279 void NaClDisConstantsParser::PrintBlockHeader() { |
| 2280 Tokens() << "constants" << Space() << OpenCurly() |
| 2281 << Space() << Space() << "// BlockID = " << GetBlockID() |
| 2282 << Endline(); |
| 2283 } |
| 2284 |
| 2285 void NaClDisConstantsParser::ProcessRecord() { |
| 2286 ObjDumpSetRecordBitAddress(Record.GetStartBit()); |
| 2287 const NaClBitcodeRecord::RecordVector Values = Record.GetValues(); |
| 2288 switch (Record.GetCode()) { |
| 2289 case naclbitc::CST_CODE_SETTYPE: |
| 2290 // SETTYPE: [typeid] |
| 2291 while (BlockTabs + 1 < GetAssemblyNumTabs()) DecAssemblyIndent(); |
| 2292 if (Values.size() == 1) { |
| 2293 ConstantType = GetType(Values[0]); |
| 2294 Tokens() << TokenizeType(ConstantType) << ":" |
| 2295 << TokenizeAbbrevIndex() << Endline(); |
| 2296 } else { |
| 2297 Errors() << "Settype record should have 1 argument. Found: " |
| 2298 << Values.size() << "\n"; |
| 2299 // Make up a type, so we can continue. |
| 2300 ConstantType = GetIntegerType(32); |
| 2301 } |
| 2302 IncAssemblyIndent(); |
| 2303 break; |
| 2304 case naclbitc::CST_CODE_UNDEF: |
| 2305 // CST_CODE_UNDEF: [] |
| 2306 if (!Values.empty()) { |
| 2307 Errors() << "Undefined record should not have arguments: Found: " |
| 2308 << Values.size() << "\n"; |
| 2309 } |
| 2310 Tokens() << NextConstId() << Space() << "=" << Space() |
| 2311 << StartCluster() << TokenizeType(ConstantType) |
| 2312 << Space() << "undef" |
| 2313 << Semicolon() << FinishCluster() |
| 2314 << TokenizeAbbrevIndex() << Endline(); |
| 2315 InstallConstantType(ConstantType); |
| 2316 break; |
| 2317 case naclbitc::CST_CODE_INTEGER: { |
| 2318 // INTEGER: [intval] |
| 2319 SignRotatedInt Value; |
| 2320 if (Values.size() == 1) { |
| 2321 const SignRotatedInt MyValue(Values[0], ConstantType); |
| 2322 Value = MyValue; |
| 2323 } else { |
| 2324 Errors() << "Integer record should have 1 argument. Found: " |
| 2325 << Values.size() << "\n"; |
| 2326 } |
| 2327 Tokens() << NextConstId() << Space() << "=" << Space() << StartCluster() |
| 2328 << StartCluster() << TokenizeType(ConstantType) << Space() |
| 2329 << Value << Semicolon() << FinishCluster() << FinishCluster() |
| 2330 << TokenizeAbbrevIndex() << Endline(); |
| 2331 InstallConstantType(ConstantType); |
| 2332 break; |
| 2333 } |
| 2334 case naclbitc::CST_CODE_FLOAT: { |
| 2335 // FLOAT: [fpval] |
| 2336 // Define initially with default value zero, in case of errors. |
| 2337 const fltSemantics &FloatRep = |
| 2338 ConstantType->isFloatTy() ? APFloat::IEEEsingle : APFloat::IEEEdouble; |
| 2339 APFloat Value(APFloat::getZero(FloatRep)); |
| 2340 if (Values.size() == 1) { |
| 2341 if (ConstantType->isFloatTy()) { |
| 2342 Value = APFloat(FloatRep, APInt(32, static_cast<uint32_t>(Values[0]))); |
| 2343 } |
| 2344 else if (ConstantType->isDoubleTy()) { |
| 2345 Value = APFloat(FloatRep, APInt(64, Values[0])); |
| 2346 } else { |
| 2347 Errors() << "Bad floating point constant argument: " |
| 2348 << Values[0] << "\n"; |
| 2349 } |
| 2350 } else { |
| 2351 Errors() << "Float record should have 1 argument. Found: " |
| 2352 << Values.size() << "\n"; |
| 2353 } |
| 2354 Tokens() << NextConstId() << Space() << "=" << Space() << StartCluster() |
| 2355 << TokenizeType(ConstantType) << Space(); |
| 2356 if (ConstantType->isFloatTy()) { |
| 2357 Tokens() << format("%g", Value.convertToFloat()); |
| 2358 } else { |
| 2359 Tokens() << format("%g", Value.convertToDouble()); |
| 2360 } |
| 2361 Tokens() << Semicolon() << FinishCluster() |
| 2362 << TokenizeAbbrevIndex() << Endline(); |
| 2363 InstallConstantType(ConstantType); |
| 2364 break; |
| 2365 } |
| 2366 default: |
| 2367 Errors() << "Unknown record in valuesymtab block.\n"; |
| 2368 break; |
| 2369 } |
| 2370 ObjDumpWrite(Record.GetStartBit(), Record); |
| 2371 } |
| 2372 |
| 2373 /// Parses and disassembles function blocks. |
| 2374 class NaClDisFunctionParser : public NaClDisBlockParser { |
| 2375 public: |
| 2376 NaClDisFunctionParser(unsigned BlockID, |
| 2377 NaClDisBlockParser *EnclosingParser); |
| 2378 |
| 2379 ~NaClDisFunctionParser() override {} |
| 2380 |
| 2381 void PrintBlockHeader() override; |
| 2382 |
| 2383 bool ParseBlock(unsigned BlockID) override; |
| 2384 |
| 2385 void ProcessRecord() override; |
| 2386 |
| 2387 /// Returns the absolute value index of the first instruction that |
| 2388 /// generates a value in the defined function. |
| 2389 uint32_t FirstValuedInstructionId() const { |
| 2390 return GetNumFunctions() + GetNumGlobals() + GetNumParams() |
| 2391 + GetNumConstants(); |
| 2392 } |
| 2393 |
| 2394 /// Converts an instruction index to the corresponding absolute value |
| 2395 /// index. |
| 2396 uint32_t ValuedInstToAbsId(uint32_t Id) const { |
| 2397 return FirstValuedInstructionId() + Id; |
| 2398 } |
| 2399 |
| 2400 /// Converts the (function) relative index to the corresponding |
| 2401 /// absolute value index. |
| 2402 uint32_t RelativeToAbsId(int32_t Id) { |
| 2403 uint32_t AbsNextId = ValuedInstToAbsId(GetNumValuedInstructions()); |
| 2404 if (Id > 0 && AbsNextId < static_cast<uint32_t>(Id)) { |
| 2405 Errors() << "Invalid relative value id: " << Id |
| 2406 << " (Must be <= " << AbsNextId << ")\n"; |
| 2407 AbsNextId = Id; |
| 2408 } |
| 2409 return AbsNextId - Id; |
| 2410 } |
| 2411 |
| 2412 /// Converts the given absolute value index to a corresponding |
| 2413 /// valued instruction index. |
| 2414 uint32_t AbsToValuedInstId(uint32_t Id) const { |
| 2415 return Id - FirstValuedInstructionId(); |
| 2416 } |
| 2417 |
| 2418 /// Returns the text representation of the encoded binary operator, |
| 2419 /// assuming the binary operator is operating on the given type. |
| 2420 /// Generates appropriate error messages if the given type is not |
| 2421 // allowed for the given Opcode. |
| 2422 const char *GetBinop(uint32_t Opcode, Type *Type); |
| 2423 |
| 2424 /// Returns the text representation of the encoded cast operator. |
| 2425 /// Generates appropriate error messages if the given Opcode is |
| 2426 /// not allowed for the given types. |
| 2427 const char *GetCastOp(uint32_t Opcode, Type *FromType, Type *ToType); |
| 2428 |
| 2429 /// Returns the text representation of the encoded integer compare |
| 2430 /// predicate. Generates appropriate error message if the given |
| 2431 /// Opcode is not defined. |
| 2432 const char *GetIcmpPredicate(uint32_t Opcode); |
| 2433 |
| 2434 /// Returns the text representation of the encoded floating point |
| 2435 /// compare predicate. Generates appropriate error message if the |
| 2436 /// given Opcode is not defined. |
| 2437 const char *GetFcmpPredicate(uint32_t Opcode); |
| 2438 |
| 2439 /// Returns the value id for the next instruction to be defined. |
| 2440 BitcodeId NextInstId() const { |
| 2441 return BitcodeId('v', GetNumValuedInstructions()); |
| 2442 } |
| 2443 |
| 2444 private: |
| 2445 // The function index of the function being defined. |
| 2446 uint32_t FcnId; |
| 2447 // The function type for the function being defined. |
| 2448 FunctionType *FcnTy; |
| 2449 // The current basic block being printed. |
| 2450 int32_t CurrentBbIndex; |
| 2451 // The expected number of basic blocks. |
| 2452 uint64_t ExpectedNumBbs; |
| 2453 // True if the previously printed instruction was a terminating |
| 2454 // instruction. Used to figure out where to insert block labels. |
| 2455 bool InstIsTerminating; |
| 2456 |
| 2457 /// Returns scalar type of vector type Ty, if vector type. Otherwise |
| 2458 /// returns Ty. |
| 2459 Type *UnderlyingType(Type *Ty) { |
| 2460 return Ty->isVectorTy() ? Ty->getVectorElementType() : Ty; |
| 2461 } |
| 2462 |
| 2463 bool isFloatingType(Type *Ty) { |
| 2464 return Ty->isFloatTy() || Ty->isDoubleTy(); |
| 2465 } |
| 2466 |
| 2467 /// Verifies that OpTy is an integer, or a vector of integers, for |
| 2468 /// operator Op. Generates error messages if appropriate. Returns Op. |
| 2469 const char *VerifyIntegerOrVectorOp(const char *Op, Type *OpTy) { |
| 2470 Type *BaseTy = OpTy; |
| 2471 if (OpTy->isVectorTy()) { |
| 2472 if (!IgnorePNaClABIChecks && |
| 2473 !PNaClABITypeChecker::isValidVectorType(OpTy)) { |
| 2474 Errors() << Op << ": invalid vector type: " << *OpTy << "\n"; |
| 2475 return Op; |
| 2476 } |
| 2477 BaseTy = OpTy->getVectorElementType(); |
| 2478 } |
| 2479 if (BaseTy->isIntegerTy()) { |
| 2480 if (IgnorePNaClABIChecks || |
| 2481 PNaClABITypeChecker::isValidScalarType(BaseTy)) { |
| 2482 return Op; |
| 2483 } |
| 2484 Errors() << Op << ": Invalid integer type: " << *OpTy << "\n"; |
| 2485 } else { |
| 2486 Errors() << Op << ": Expects integer type. Found: " << *OpTy << "\n"; |
| 2487 } |
| 2488 return Op; |
| 2489 } |
| 2490 |
| 2491 /// Verifies that Opty is a floating point type, or a vector of a |
| 2492 /// floating points, for operator Op. Generates error messages if |
| 2493 /// appropriate. Returns Op. |
| 2494 const char *VerifyFloatingOrVectorOp(const char *Op, Type *OpTy) { |
| 2495 Type *BaseTy = OpTy; |
| 2496 if (OpTy->isVectorTy()) { |
| 2497 if (!IgnorePNaClABIChecks && |
| 2498 !PNaClABITypeChecker::isValidVectorType(OpTy)) { |
| 2499 Errors() << Op << ": invalid vector type: " << *OpTy << "\n"; |
| 2500 return Op; |
| 2501 } |
| 2502 BaseTy = OpTy->getVectorElementType(); |
| 2503 } |
| 2504 if (!isFloatingType(BaseTy)) { |
| 2505 Errors() << Op << ": Expects floating point. Found " |
| 2506 << OpTy << "\n"; |
| 2507 return Op; |
| 2508 } |
| 2509 if (!IgnorePNaClABIChecks && |
| 2510 !PNaClABITypeChecker::isValidScalarType(BaseTy)) { |
| 2511 Errors() << Op << ": type not allowed: " << OpTy << "\n"; |
| 2512 } |
| 2513 return Op; |
| 2514 } |
| 2515 |
| 2516 /// Op is the name of the operation that called this. Checks if |
| 2517 /// OpTy is either a (non-void) scalar, or a vector of scalars. If |
| 2518 /// not, generates an appropriate error message. Always returns Op. |
| 2519 const char *VerifyScalarOrVectorOp(const char *Op, Type *OpTy) { |
| 2520 if (IgnorePNaClABIChecks) return Op; |
| 2521 if (PNaClABITypeChecker::isValidScalarType(OpTy)) { |
| 2522 if (OpTy->isVoidTy()) |
| 2523 Errors() << Op << ": Type void not allowed\n"; |
| 2524 } else if (!PNaClABITypeChecker::isValidVectorType(OpTy)) { |
| 2525 Errors() << Op << ": Expects scalar/vector type. Found: " |
| 2526 << OpTy << "\n"; |
| 2527 } |
| 2528 return Op; |
| 2529 } |
| 2530 |
| 2531 void VerifyIndexedVector(const char *Op, uint32_t VecValue, |
| 2532 uint32_t IdxValue) { |
| 2533 Type *VecType = GetValueType(VecValue); |
| 2534 Type *IdxType = GetValueType(IdxValue); |
| 2535 if (!IgnorePNaClABIChecks && |
| 2536 !PNaClABITypeChecker::isValidVectorType(VecType)){ |
| 2537 if (VecType->isVectorTy()) |
| 2538 Errors() << Op << ": Vector type " << *VecType << " not allowed\n"; |
| 2539 else |
| 2540 Errors() << Op << ": Vector type expected. Found: " << *VecType << "\n"; |
| 2541 } |
| 2542 // Note: This restriction appears to be LLVM specific. |
| 2543 if (!IdxType->isIntegerTy(32)) { |
| 2544 Errors() << Op << ": Index not i32. Found: " << *IdxType << "\n"; |
| 2545 } |
| 2546 BitcodeId IdxId(GetBitcodeId(IdxValue)); |
| 2547 if (IdxId.GetKind() != 'c') { |
| 2548 Errors() << Op << ": Vector index not constant: " << IdxId << "\n"; |
| 2549 // TODO(kschimpf): We should check that Idx is a constant with |
| 2550 // valid access. However, we currently don't store constant |
| 2551 // values, so it can't be tested. |
| 2552 } |
| 2553 } |
| 2554 |
| 2555 /// Checks if block Value is a valid branch target for the current |
| 2556 /// function block. If not, generates an appropriate error message. |
| 2557 void VerifyBranchRange(uint64_t Value) { |
| 2558 if (0 == Value || Value >= ExpectedNumBbs) { |
| 2559 Errors() << "Branch " << BitcodeId('b', Value) |
| 2560 << " out of range. Not in [1," << ExpectedNumBbs << "]\n"; |
| 2561 } |
| 2562 } |
| 2563 |
| 2564 /// Convert alignment exponent (i.e. power of two (or zero)) to the |
| 2565 /// corresponding alignment to use. If alignment is too large, it generates |
| 2566 /// an error message and returns 0. |
| 2567 unsigned getAlignmentValue(uint64_t Exponent); |
| 2568 }; |
| 2569 |
| 2570 NaClDisFunctionParser::NaClDisFunctionParser( |
| 2571 unsigned BlockID, |
| 2572 NaClDisBlockParser *EnclosingParser) |
| 2573 : NaClDisBlockParser(BlockID, EnclosingParser), |
| 2574 CurrentBbIndex(-1), |
| 2575 ExpectedNumBbs(0), |
| 2576 InstIsTerminating(false) { |
| 2577 Context->ResetLocalCounters(); |
| 2578 if (Context->HasNextDefinedFunctionIndex()) { |
| 2579 FcnId = Context->GetNextDefinedFunctionIndex(); |
| 2580 FcnTy = GetFunctionType(FcnId); |
| 2581 } else { |
| 2582 FcnId = 0; |
| 2583 SmallVector<Type*, 8> Signature; |
| 2584 FcnTy = FunctionType::get(GetVoidType(), Signature, 0); |
| 2585 Errors() << |
| 2586 "No corresponding defining function address for function block.\n"; |
| 2587 return; |
| 2588 } |
| 2589 Context->IncNumDefinedFunctions(); |
| 2590 |
| 2591 // Now install parameters. |
| 2592 for (size_t Index = 0; Index < FcnTy->getFunctionNumParams(); ++Index) { |
| 2593 InstallParamType(FcnTy->getFunctionParamType(Index)); |
| 2594 } |
| 2595 } |
| 2596 |
| 2597 void NaClDisFunctionParser::PrintBlockHeader() { |
| 2598 Tokens() << "function" << Space(); |
| 2599 BitcodeId FunctionId('f', FcnId); |
| 2600 bool InvalidSignature = true; // until proven otherwise. |
| 2601 if (Context->IsFunctionIntrinsic(FcnId)) |
| 2602 InvalidSignature = false; |
| 2603 else if (IgnorePNaClABIChecks || |
| 2604 PNaClABITypeChecker::isValidFunctionType(FcnTy)) { |
| 2605 InvalidSignature = false; |
| 2606 } |
| 2607 if (InvalidSignature) { |
| 2608 Errors() << "Invalid type signature for " |
| 2609 << BitcodeId('f', FcnId) << ": " << *FcnTy << "\n"; |
| 2610 } |
| 2611 Tokens() << TokenizeFunctionSignature(FcnTy, &FunctionId) |
| 2612 << Space() << OpenCurly() |
| 2613 << Space() << Space() << "// BlockID = " << GetBlockID() |
| 2614 << Endline(); |
| 2615 } |
| 2616 |
| 2617 const char *NaClDisFunctionParser::GetBinop(uint32_t Opcode, Type *Ty) { |
| 2618 Instruction::BinaryOps LLVMOpcode; |
| 2619 if (!naclbitc::DecodeBinaryOpcode(Opcode, Ty, LLVMOpcode)) { |
| 2620 Errors() << "Binary opcode not understood: " << Opcode << "\n"; |
| 2621 return "???"; |
| 2622 } |
| 2623 switch (LLVMOpcode) { |
| 2624 default: |
| 2625 Errors() << "Binary opcode not understood: " << Opcode << "\n"; |
| 2626 return "???"; |
| 2627 case Instruction::Add: |
| 2628 return VerifyIntArithmeticOp("add", Ty); |
| 2629 case Instruction::FAdd: |
| 2630 return VerifyFloatingOrVectorOp("fadd", Ty); |
| 2631 case Instruction::Sub: |
| 2632 return VerifyIntArithmeticOp("sub", Ty); |
| 2633 case Instruction::FSub: |
| 2634 return VerifyFloatingOrVectorOp("fsub", Ty); |
| 2635 case Instruction::Mul: |
| 2636 return VerifyIntArithmeticOp("mul", Ty); |
| 2637 case Instruction::FMul: |
| 2638 return VerifyFloatingOrVectorOp("fmul", Ty); |
| 2639 case Instruction::UDiv: |
| 2640 return VerifyIntArithmeticOp("udiv", Ty); |
| 2641 case Instruction::SDiv: |
| 2642 return VerifyIntArithmeticOp("sdiv", Ty); |
| 2643 case Instruction::FDiv: |
| 2644 return VerifyFloatingOrVectorOp("fdiv", Ty); |
| 2645 case Instruction::URem: |
| 2646 return VerifyIntArithmeticOp("urem", Ty); |
| 2647 case Instruction::SRem: |
| 2648 return VerifyIntArithmeticOp("srem", Ty); |
| 2649 case Instruction::FRem: |
| 2650 return VerifyFloatingOrVectorOp("frem", Ty); |
| 2651 case Instruction::Shl: |
| 2652 return VerifyIntArithmeticOp("shl", Ty); |
| 2653 case Instruction::LShr: |
| 2654 return VerifyIntArithmeticOp("lshr", Ty); |
| 2655 case Instruction::AShr: |
| 2656 return VerifyIntArithmeticOp("ashr", Ty); |
| 2657 case Instruction::And: |
| 2658 return VerifyIntegerOrVectorOp("and", Ty); |
| 2659 case Instruction::Or: |
| 2660 return VerifyIntegerOrVectorOp("or", Ty); |
| 2661 case Instruction::Xor: |
| 2662 return VerifyIntegerOrVectorOp("xor", Ty); |
| 2663 } |
| 2664 } |
| 2665 |
| 2666 const char *NaClDisFunctionParser::GetCastOp(uint32_t Opcode, |
| 2667 Type *FromType, Type *ToType) { |
| 2668 Instruction::CastOps Cast; |
| 2669 const char *CastName = "???"; |
| 2670 if (!naclbitc::DecodeCastOpcode(Opcode, Cast)) { |
| 2671 Errors() << "Cast opcode not understood: " << Opcode << "\n"; |
| 2672 return CastName; |
| 2673 } |
| 2674 switch (Cast) { |
| 2675 default: |
| 2676 Errors() << "Cast opcode not understood: " << Opcode << "\n"; |
| 2677 return CastName; |
| 2678 case Instruction::BitCast: |
| 2679 CastName = "bitcast"; |
| 2680 break; |
| 2681 case Instruction::Trunc: |
| 2682 CastName = "trunc"; |
| 2683 break; |
| 2684 case Instruction::ZExt: |
| 2685 CastName = "zext"; |
| 2686 break; |
| 2687 case Instruction::SExt: |
| 2688 CastName = "sext"; |
| 2689 break; |
| 2690 case Instruction::FPToUI: |
| 2691 CastName = "fptoui"; |
| 2692 break; |
| 2693 case Instruction::FPToSI: |
| 2694 CastName = "fptosi"; |
| 2695 break; |
| 2696 case Instruction::UIToFP: |
| 2697 CastName = "uitofp"; |
| 2698 break; |
| 2699 case Instruction::SIToFP: |
| 2700 CastName = "sitofp"; |
| 2701 break; |
| 2702 case Instruction::FPTrunc: |
| 2703 CastName = "fptrunc"; |
| 2704 break; |
| 2705 case Instruction::FPExt: |
| 2706 CastName = "fpext"; |
| 2707 break; |
| 2708 } |
| 2709 if (!CastInst::castIsValid(Cast, FromType, ToType)) { |
| 2710 Errors() << "Invalid cast '" << CastName << "'. Not defined on " |
| 2711 << FromType << " to " << ToType << "\n"; |
| 2712 } |
| 2713 return CastName; |
| 2714 } |
| 2715 |
| 2716 const char *NaClDisFunctionParser::GetIcmpPredicate(uint32_t Opcode) { |
| 2717 CmpInst::Predicate Predicate; |
| 2718 if (!naclbitc::DecodeIcmpPredicate(Opcode, Predicate)) { |
| 2719 Errors() << "Icmp predicate not understood: " << Opcode << "\n"; |
| 2720 return "???"; |
| 2721 } |
| 2722 switch (Predicate) { |
| 2723 default: |
| 2724 Errors() << "Icmp predicate not understood: " << Opcode << "\n"; |
| 2725 return "???"; |
| 2726 case CmpInst::ICMP_EQ: |
| 2727 return "eq"; |
| 2728 case CmpInst::ICMP_NE: |
| 2729 return "ne"; |
| 2730 case CmpInst::ICMP_UGT: |
| 2731 return "ugt"; |
| 2732 case CmpInst::ICMP_UGE: |
| 2733 return "uge"; |
| 2734 case CmpInst::ICMP_ULT: |
| 2735 return "ult"; |
| 2736 case CmpInst::ICMP_ULE: |
| 2737 return "ule"; |
| 2738 case CmpInst::ICMP_SGT: |
| 2739 return "sgt"; |
| 2740 case CmpInst::ICMP_SGE: |
| 2741 return "sge"; |
| 2742 case CmpInst::ICMP_SLT: |
| 2743 return "slt"; |
| 2744 case CmpInst::ICMP_SLE: |
| 2745 return "sle"; |
| 2746 } |
| 2747 } |
| 2748 |
| 2749 const char *NaClDisFunctionParser::GetFcmpPredicate(uint32_t Opcode) { |
| 2750 CmpInst::Predicate Predicate; |
| 2751 if (!naclbitc::DecodeFcmpPredicate(Opcode, Predicate)) { |
| 2752 Errors() << "Fcmp predicate not understood: " << Opcode << "\n"; |
| 2753 return "???"; |
| 2754 } |
| 2755 switch (Predicate) { |
| 2756 default: |
| 2757 Errors() << "Fcmp predicate not understood: " << Opcode << "\n"; |
| 2758 return "???"; |
| 2759 case CmpInst::FCMP_FALSE: |
| 2760 return "false"; |
| 2761 case CmpInst::FCMP_OEQ: |
| 2762 return "oeq"; |
| 2763 case CmpInst::FCMP_OGT: |
| 2764 return "ogt"; |
| 2765 case CmpInst::FCMP_OGE: |
| 2766 return "oge"; |
| 2767 case CmpInst::FCMP_OLT: |
| 2768 return "olt"; |
| 2769 case CmpInst::FCMP_OLE: |
| 2770 return "ole"; |
| 2771 case CmpInst::FCMP_ONE: |
| 2772 return "one"; |
| 2773 case CmpInst::FCMP_ORD: |
| 2774 return "ord"; |
| 2775 case CmpInst::FCMP_UNO: |
| 2776 return "uno"; |
| 2777 case CmpInst::FCMP_UEQ: |
| 2778 return "ueq"; |
| 2779 case CmpInst::FCMP_UGT: |
| 2780 return "ugt"; |
| 2781 case CmpInst::FCMP_UGE: |
| 2782 return "uge"; |
| 2783 case CmpInst::FCMP_ULT: |
| 2784 return "ult"; |
| 2785 case CmpInst::FCMP_ULE: |
| 2786 return "ule"; |
| 2787 case CmpInst::FCMP_UNE: |
| 2788 return "une"; |
| 2789 case CmpInst::FCMP_TRUE: |
| 2790 return "true"; |
| 2791 } |
| 2792 } |
| 2793 |
| 2794 namespace { |
| 2795 |
| 2796 static const unsigned MaxAlignmentExponent = 29; |
| 2797 static_assert( |
| 2798 (1u << MaxAlignmentExponent) == Value::MaximumAlignment, |
| 2799 "Inconsistency between Value.MaxAlignment and PNaCl alignment limit"); |
| 2800 } |
| 2801 |
| 2802 unsigned NaClDisFunctionParser::getAlignmentValue(uint64_t Exponent) { |
| 2803 if (Exponent > MaxAlignmentExponent + 1) { |
| 2804 Errors() << "Alignment can't be greater than 2**" << MaxAlignmentExponent |
| 2805 << ". Found: 2**" << (Exponent - 1) << "\n"; |
| 2806 return 0; |
| 2807 } |
| 2808 return (1 << static_cast<unsigned>(Exponent)) >> 1; |
| 2809 } |
| 2810 |
| 2811 bool NaClDisFunctionParser::ParseBlock(unsigned BlockID) { |
| 2812 ObjDumpSetRecordBitAddress(GetBlock().GetStartBit()); |
| 2813 switch (BlockID) { |
| 2814 case naclbitc::CONSTANTS_BLOCK_ID: { |
| 2815 NaClDisConstantsParser Parser(BlockID, this); |
| 2816 return Parser.ParseThisBlock(); |
| 2817 } |
| 2818 case naclbitc::VALUE_SYMTAB_BLOCK_ID: { |
| 2819 if (!PNaClAllowLocalSymbolTables) break; |
| 2820 NaClDisValueSymtabParser Parser(BlockID, this); |
| 2821 return Parser.ParseThisBlock(); |
| 2822 } |
| 2823 default: |
| 2824 break; |
| 2825 } |
| 2826 return NaClDisBlockParser::ParseBlock(BlockID); |
| 2827 } |
| 2828 |
| 2829 void NaClDisFunctionParser::ProcessRecord() { |
| 2830 ObjDumpSetRecordBitAddress(Record.GetStartBit()); |
| 2831 const NaClBitcodeRecord::RecordVector Values = Record.GetValues(); |
| 2832 // Start by adding block label if previous instruction is terminating. |
| 2833 if (InstIsTerminating) { |
| 2834 InstIsTerminating = false; |
| 2835 ++CurrentBbIndex; |
| 2836 DecAssemblyIndent(); |
| 2837 Tokens() << BitcodeId('b', CurrentBbIndex) << ":" << Endline(); |
| 2838 ObjDumpFlush(); |
| 2839 IncAssemblyIndent(); |
| 2840 } |
| 2841 switch (Record.GetCode()) { |
| 2842 case naclbitc::FUNC_CODE_DECLAREBLOCKS: |
| 2843 // DECLAREBLOCKS: [n] |
| 2844 InstIsTerminating = true; // Force block label on first instruction. |
| 2845 if (Values.size() != 1) { |
| 2846 Errors() << "Function blocks record expects a size argument.\n"; |
| 2847 break; |
| 2848 } |
| 2849 ExpectedNumBbs = Values[0]; |
| 2850 if (ExpectedNumBbs == 0) { |
| 2851 Errors() << "Functions must contain at least one block.\n"; |
| 2852 } |
| 2853 Tokens() << "blocks" << Space() << ExpectedNumBbs << Semicolon(); |
| 2854 break; |
| 2855 case naclbitc::FUNC_CODE_INST_BINOP: { |
| 2856 // BINOP: [opval, opval, opcode] |
| 2857 if (Values.size() != 3) { |
| 2858 Errors() << "Binop record expects 3 arguments. Found: " |
| 2859 << Values.size() << "\n"; |
| 2860 break; |
| 2861 } |
| 2862 uint32_t Op1 = RelativeToAbsId(Values[0]); |
| 2863 uint32_t Op2 = RelativeToAbsId(Values[1]); |
| 2864 Type *Type1 = GetValueType(Op1); |
| 2865 Type *Type2 = GetValueType(Op2); |
| 2866 if (Type1 != Type2) { |
| 2867 Errors() << "Binop argument types differ: " << *Type1 << " and " |
| 2868 << *Type2 << "\n"; |
| 2869 } |
| 2870 const char *Binop = GetBinop(Values[2], Type1); |
| 2871 Tokens() << NextInstId() << Space() << "=" << Space() << Binop << Space() |
| 2872 << TokenizeType(Type1) << Space() << GetBitcodeId(Op1) << Comma() |
| 2873 << Space() << GetBitcodeId(Op2) << Semicolon(); |
| 2874 InstallInstType(Type1); |
| 2875 break; |
| 2876 } |
| 2877 case naclbitc::FUNC_CODE_INST_CAST: { |
| 2878 // CAST: [opval, destty, castopc] |
| 2879 if (Values.size() != 3) { |
| 2880 Errors() << "Cast record expects 3 argments. Found: " |
| 2881 << Values.size() << "\n"; |
| 2882 break; |
| 2883 } |
| 2884 uint32_t Op = RelativeToAbsId(Values[0]); |
| 2885 Type *FromType = GetValueType(Op); |
| 2886 Type *ToType = GetType(Values[1]); |
| 2887 const char *CastOp = GetCastOp(Values[2], FromType, ToType); |
| 2888 Tokens() << NextInstId() << Space() << "=" << Space() << CastOp << Space() |
| 2889 << TokenizeType(FromType) << Space() << GetBitcodeId(Op) |
| 2890 << Space() << "to" << Space() << TokenizeType(ToType) |
| 2891 << Semicolon(); |
| 2892 InstallInstType(ToType); |
| 2893 break; |
| 2894 } |
| 2895 case naclbitc::FUNC_CODE_INST_RET: { |
| 2896 // RET: [opval?] |
| 2897 InstIsTerminating = true; |
| 2898 Tokens() << "ret" << Space(); |
| 2899 switch (Values.size()) { |
| 2900 default: |
| 2901 Errors() << "Function return record expects an optional return argument. " |
| 2902 << "Found: " << Values.size() << " arguments\n"; |
| 2903 break; |
| 2904 case 0: |
| 2905 Tokens() << "void"; |
| 2906 break; |
| 2907 case 1: { |
| 2908 uint32_t Op = RelativeToAbsId(Values[0]); |
| 2909 Tokens() << TokenizeType(GetValueType(Op)) << Space()<< GetBitcodeId(Op); |
| 2910 break; |
| 2911 } |
| 2912 } |
| 2913 Tokens() << Semicolon(); |
| 2914 break; |
| 2915 } |
| 2916 case naclbitc::FUNC_CODE_INST_BR: { |
| 2917 // BR: [bb#, bb#, opval] or [bb#] |
| 2918 InstIsTerminating = true; |
| 2919 if (Values.size() != 1 && Values.size() != 3) { |
| 2920 Errors() << "Function branch record expects 1 or 3 arguments. Found: " |
| 2921 << Values.size() << "\n"; |
| 2922 break; |
| 2923 } |
| 2924 Tokens() << "br" << Space(); |
| 2925 if (Values.size() == 3) { |
| 2926 uint32_t OpIndex = RelativeToAbsId(Values[2]); |
| 2927 if (GetValueType(OpIndex) != GetComparisonType()) |
| 2928 Errors() << "Branch condition not i1\n"; |
| 2929 Tokens() << StartCluster() << "i1" << Space() << GetBitcodeId(OpIndex) |
| 2930 << Comma() << FinishCluster() << Space(); |
| 2931 } |
| 2932 VerifyBranchRange(Values[0]); |
| 2933 Tokens() << StartCluster() << "label" << Space() |
| 2934 << BitcodeId('b', Values[0]); |
| 2935 if (Values.size() == 3) { |
| 2936 VerifyBranchRange(Values[1]); |
| 2937 Tokens() << Comma() << FinishCluster() << Space() |
| 2938 << StartCluster() << "label" << Space() |
| 2939 << BitcodeId('b', Values[1]); |
| 2940 } |
| 2941 Tokens() << Semicolon() << FinishCluster(); |
| 2942 break; |
| 2943 } |
| 2944 case naclbitc::FUNC_CODE_INST_SWITCH: { |
| 2945 // SWITCH: [opty, op, bb#, n, (1, 1, int, bb#)*] |
| 2946 InstIsTerminating = true; |
| 2947 if (Values.size() < 4) { |
| 2948 Errors() |
| 2949 << "Function switch record expects at least 4 arguments. Found: " |
| 2950 << Values.size() << "\n"; |
| 2951 break; |
| 2952 } |
| 2953 Type *OpType = GetType(Values[0]); |
| 2954 uint32_t CondId = RelativeToAbsId(Values[1]); |
| 2955 Type *CondType = GetValueType(CondId); |
| 2956 if (OpType != CondType) |
| 2957 Errors() << "Specified select type " << *OpType << " but found: " |
| 2958 << *CondType << "\n"; |
| 2959 if (!IgnorePNaClABIChecks && |
| 2960 !PNaClABITypeChecker::isValidSwitchConditionType(CondType)) { |
| 2961 Errors() << PNaClABITypeChecker::ExpectedSwitchConditionType(CondType) |
| 2962 << "\n"; |
| 2963 } |
| 2964 uint32_t DefaultBb = Values[2]; |
| 2965 unsigned NumCases = Values[3]; |
| 2966 VerifyBranchRange(DefaultBb); |
| 2967 Tokens() << "switch" << Space() << StartCluster() << StartCluster() |
| 2968 << TokenizeType(OpType) << Space() << GetBitcodeId(CondId) |
| 2969 << FinishCluster() << Space() << "{" << FinishCluster() |
| 2970 << Endline(); |
| 2971 IncAssemblyIndent(); |
| 2972 Tokens() << StartCluster() << "default" << ":" << Space() |
| 2973 << FinishCluster() << StartCluster() << "br" << Space() << "label" |
| 2974 << Space() << BitcodeId('b', DefaultBb) << Semicolon() |
| 2975 << FinishCluster() << Endline(); |
| 2976 unsigned CurIdx = 4; |
| 2977 for (unsigned i = 0; i < NumCases; ++i) { |
| 2978 unsigned NumItems = Values[CurIdx++]; |
| 2979 bool IsSingleNumber = Values[CurIdx++]; |
| 2980 if (NumItems != 1 || !IsSingleNumber) { |
| 2981 Errors() << "Case ranges are not supported in PNaCl\n"; |
| 2982 break; |
| 2983 } |
| 2984 SignRotatedInt CaseValue(Values[CurIdx++], OpType); |
| 2985 // TODO(kschimpf) Check if CaseValue possible based on OpType. |
| 2986 uint64_t Label = Values[CurIdx++]; |
| 2987 VerifyBranchRange(Label); |
| 2988 Tokens() << StartCluster() << TokenizeType(OpType) << Space() |
| 2989 << CaseValue << ":" << Space() << FinishCluster() |
| 2990 << StartCluster() << "br" << Space() << "label" << Space() |
| 2991 << BitcodeId('b', Label) << Semicolon() << FinishCluster() |
| 2992 << Endline(); |
| 2993 } |
| 2994 DecAssemblyIndent(); |
| 2995 Tokens() << "}"; |
| 2996 break; |
| 2997 } |
| 2998 case naclbitc::FUNC_CODE_INST_UNREACHABLE: |
| 2999 // UNREACHABLE |
| 3000 InstIsTerminating = true; |
| 3001 if (!Values.empty()) { |
| 3002 Errors() << "Function unreachable record expects no arguments. Found: " |
| 3003 << Values.size() << "\n"; |
| 3004 } |
| 3005 Tokens() << "unreachable" << Semicolon(); |
| 3006 break; |
| 3007 case naclbitc::FUNC_CODE_INST_PHI: { |
| 3008 // PHI: [ty, (val0, bb0)*] |
| 3009 if (Values.size() < 3) { |
| 3010 Errors() << "Function phi record expects at least 3 arguments. Found: " |
| 3011 << Values.size() << "\n"; |
| 3012 break; |
| 3013 } else if (Values.size() % 2 == 0) { |
| 3014 Errors() |
| 3015 << "Function phi records should have an odd number of arguments. " |
| 3016 << "Found: " << Values.size() << "\n"; |
| 3017 } |
| 3018 Type* OpType = GetType(Values[0]); |
| 3019 Tokens() << NextInstId() << Space() << "=" << StartCluster() << Space() |
| 3020 << "phi" << Space() << TokenizeType(OpType); |
| 3021 for (size_t i = 1; i < Values.size(); i += 2) { |
| 3022 if (i > 1) Tokens() << Comma(); |
| 3023 uint32_t Index = RelativeToAbsId(NaClDecodeSignRotatedValue(Values[i])); |
| 3024 Tokens() << FinishCluster() << Space() << StartCluster() << OpenSquare() |
| 3025 << GetBitcodeId(Index) << Comma() << Space() |
| 3026 << BitcodeId('b', Values[i+1]) << CloseSquare(); |
| 3027 } |
| 3028 Tokens() << Semicolon() << FinishCluster(); |
| 3029 InstallInstType(OpType); |
| 3030 break; |
| 3031 }; |
| 3032 case naclbitc::FUNC_CODE_INST_ALLOCA: { |
| 3033 // ALLOCA: [size, align] |
| 3034 if (Values.size() != 2) { |
| 3035 Errors() << "Function alloca record expects 2 arguments. Found: " |
| 3036 << Values.size() << "\n"; |
| 3037 break; |
| 3038 } |
| 3039 uint32_t SizeOp = RelativeToAbsId(Values[0]); |
| 3040 Type* SizeType = GetValueType(SizeOp); |
| 3041 BitcodeId SizeId(GetBitcodeId(SizeOp)); |
| 3042 unsigned Alignment = getAlignmentValue(Values[1]); |
| 3043 if (!IgnorePNaClABIChecks && !PNaClABIProps::isAllocaSizeType(SizeType)) |
| 3044 Errors() << PNaClABIProps::ExpectedAllocaSizeType() << "\n"; |
| 3045 // TODO(kschimpf) Are there any constraints on alignment? |
| 3046 Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster() |
| 3047 << "alloca" << Space() << "i8" << Comma() << FinishCluster() |
| 3048 << Space() << StartCluster() << TokenizeType(SizeType) << Space() |
| 3049 << SizeId << Comma() << FinishCluster() << Space() |
| 3050 << StartCluster() <<"align" << Space() << Alignment << Semicolon() |
| 3051 << FinishCluster(); |
| 3052 InstallInstType(GetPointerType()); |
| 3053 break; |
| 3054 } |
| 3055 case naclbitc::FUNC_CODE_INST_LOAD: { |
| 3056 // LOAD: [op, align, ty] |
| 3057 if (Values.size() != 3) { |
| 3058 Errors() << "Function load record expects 3 arguments. Found: " |
| 3059 << Values.size() << "\n"; |
| 3060 break; |
| 3061 } |
| 3062 unsigned Alignment = getAlignmentValue(Values[1]); |
| 3063 Type *LoadType = GetType(Values[2]); |
| 3064 VerifyScalarOrVectorOp("load", LoadType); |
| 3065 Context->VerifyMemoryAccessAlignment("load", LoadType, Alignment); |
| 3066 Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster() |
| 3067 << "load" << Space() << TokenizeType(LoadType) << "*" << Space() |
| 3068 << GetBitcodeId(RelativeToAbsId(Values[0])) << Comma() |
| 3069 << FinishCluster() << Space() << StartCluster() |
| 3070 << "align" << Space() << Alignment << Semicolon() |
| 3071 << FinishCluster(); |
| 3072 InstallInstType(LoadType); |
| 3073 break; |
| 3074 } |
| 3075 case naclbitc::FUNC_CODE_INST_STORE: { |
| 3076 // STORE: [ptr, val, align] |
| 3077 if (Values.size() != 3) { |
| 3078 Errors() << "Function store record expects 3 arguments. Found: " |
| 3079 << Values.size() << "\n"; |
| 3080 break; |
| 3081 } |
| 3082 unsigned Alignment = getAlignmentValue(Values[2]); |
| 3083 uint32_t Val = RelativeToAbsId(Values[1]); |
| 3084 Type *ValType = GetValueType(Val); |
| 3085 VerifyScalarOrVectorOp("store", ValType); |
| 3086 Context->VerifyMemoryAccessAlignment("store", ValType, Alignment); |
| 3087 Tokens() << StartCluster() << "store" << Space() << TokenizeType(ValType) |
| 3088 << Space() << GetBitcodeId(Val) << Comma() << FinishCluster() |
| 3089 << Space() << StartCluster() << TokenizeType(ValType) << "*" |
| 3090 << Space() << GetBitcodeId(RelativeToAbsId(Values[0])) << Comma() |
| 3091 << FinishCluster() << Space() << StartCluster() << "align" |
| 3092 << Space() << Alignment << Semicolon() << FinishCluster(); |
| 3093 break; |
| 3094 } |
| 3095 case naclbitc::FUNC_CODE_INST_CMP2: { |
| 3096 // CMP2: [opval, opval, pred] |
| 3097 if (Values.size() != 3) { |
| 3098 Errors() << "Function compare record expects 3 arguments. Found: " |
| 3099 << Values.size() << "\n"; |
| 3100 break; |
| 3101 } |
| 3102 uint32_t Arg1 = RelativeToAbsId(Values[0]); |
| 3103 uint32_t Arg2 = RelativeToAbsId(Values[1]); |
| 3104 Type *Arg1Type = GetValueType(Arg1); |
| 3105 Type *Arg2Type = GetValueType(Arg2); |
| 3106 if (Arg1Type != Arg2Type) { |
| 3107 Errors() << "Arguments not of same type: " << *Arg1Type << " and " |
| 3108 << *Arg2Type << "\n"; |
| 3109 } |
| 3110 const char *Pred = "???"; |
| 3111 Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster(); |
| 3112 Type* BaseType = UnderlyingType(Arg1Type); |
| 3113 if (BaseType->isIntegerTy()) { |
| 3114 Pred = GetIcmpPredicate(Values[2]); |
| 3115 Tokens() << "icmp" << Space() << Pred; |
| 3116 } else if (isFloatingType(BaseType)) { |
| 3117 Pred = GetFcmpPredicate(Values[2]); |
| 3118 Tokens() << "fcmp" << Space() << Pred; |
| 3119 } else { |
| 3120 Errors() << "Compare not on integer/float type. Found: " |
| 3121 << *Arg1Type << "\n"; |
| 3122 Tokens() << "cmp" << Space() << "???" "(" << Values[2] << ")"; |
| 3123 } |
| 3124 Tokens() << FinishCluster() << Space() << StartCluster() |
| 3125 << TokenizeType(Arg1Type) << Space () << GetBitcodeId(Arg1) |
| 3126 << Comma() << FinishCluster() << Space() << StartCluster() |
| 3127 << GetBitcodeId(Arg2) << Semicolon() << FinishCluster(); |
| 3128 Type *ResultType = GetComparisonType(); |
| 3129 if (Arg1Type->isVectorTy()) { |
| 3130 ResultType = VectorType::get(ResultType, |
| 3131 Arg1Type->getVectorNumElements()); |
| 3132 } |
| 3133 InstallInstType(ResultType); |
| 3134 break; |
| 3135 } |
| 3136 case naclbitc::FUNC_CODE_INST_VSELECT: { |
| 3137 // VSELECT: [opval, opval, pred] |
| 3138 if (Values.size() != 3) { |
| 3139 Errors() << "Select record expects 3 arguments. Found: " |
| 3140 << Values.size() << "\n"; |
| 3141 break; |
| 3142 } |
| 3143 uint32_t CondValue = RelativeToAbsId(Values[2]); |
| 3144 uint32_t ThenValue = RelativeToAbsId(Values[0]); |
| 3145 uint32_t ElseValue = RelativeToAbsId(Values[1]); |
| 3146 Type *CondType = GetValueType(CondValue); |
| 3147 Type *ThenType = GetValueType(ThenValue); |
| 3148 Type *ElseType = GetValueType(ElseValue); |
| 3149 if (ThenType != ElseType) { |
| 3150 Errors() << "Selected arguments not of same type: " |
| 3151 << *ThenType << " and " << *ElseType << "\n"; |
| 3152 } |
| 3153 Type *BaseType = UnderlyingType(ThenType); |
| 3154 if (!(BaseType->isIntegerTy() || isFloatingType(BaseType))) { |
| 3155 Errors() << "Select arguments not integer/float. Found: " << *ThenType; |
| 3156 } |
| 3157 Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster() |
| 3158 << "select" << Space() << TokenizeType(CondType) << Space() |
| 3159 << GetBitcodeId(CondValue) << Comma() << FinishCluster() << Space() |
| 3160 << StartCluster() << TokenizeType(ThenType) << Space() |
| 3161 << GetBitcodeId(ThenValue) << Comma() << FinishCluster() << Space() |
| 3162 << StartCluster() << TokenizeType(ElseType) << Space() |
| 3163 << GetBitcodeId(ElseValue) << Semicolon() |
| 3164 << FinishCluster(); |
| 3165 InstallInstType(ThenType); |
| 3166 break; |
| 3167 } |
| 3168 case naclbitc::FUNC_CODE_INST_EXTRACTELT: { |
| 3169 // EXTRACTELT: [opval, opval] |
| 3170 if (Values.size() != 2) { |
| 3171 Errors() << "Extract element record expects 2 arguments. Found: " |
| 3172 << Values.size() << "\n"; |
| 3173 break; |
| 3174 } |
| 3175 uint32_t VecValue = RelativeToAbsId(Values[0]); |
| 3176 uint32_t IdxValue = RelativeToAbsId(Values[1]); |
| 3177 VerifyIndexedVector("extractelement", VecValue, IdxValue); |
| 3178 Type *VecType = GetValueType(VecValue); |
| 3179 Type *IdxType = GetValueType(IdxValue); |
| 3180 Tokens() << NextInstId() << Space() << " = " << Space() << StartCluster() |
| 3181 << "extractelement" << Space() << TokenizeType(VecType) << Space() |
| 3182 << GetBitcodeId(VecValue) << Comma() << FinishCluster() << Space() |
| 3183 << StartCluster() << TokenizeType(IdxType) << Space() |
| 3184 << GetBitcodeId(IdxValue) << Semicolon() << FinishCluster(); |
| 3185 InstallInstType(UnderlyingType(VecType)); |
| 3186 break; |
| 3187 } |
| 3188 case naclbitc::FUNC_CODE_INST_INSERTELT: { |
| 3189 // INSERTELT: [opval, opval, opval] |
| 3190 uint32_t VecValue = RelativeToAbsId(Values[0]); |
| 3191 uint32_t EltValue = RelativeToAbsId(Values[1]); |
| 3192 uint32_t IdxValue = RelativeToAbsId(Values[2]); |
| 3193 VerifyIndexedVector("insertelement", VecValue, IdxValue); |
| 3194 Type *VecType = GetValueType(VecValue); |
| 3195 Type *EltType = GetValueType(EltValue); |
| 3196 Type *IdxType = GetValueType(IdxValue); |
| 3197 if (EltType != UnderlyingType(VecType)) { |
| 3198 Errors() << "insertelement: Illegal element type " << *EltType |
| 3199 << ". Expected: " << *UnderlyingType(VecType) << "\n"; |
| 3200 } |
| 3201 Tokens() << NextInstId() << Space() << " = " << Space() << StartCluster() |
| 3202 << "insertelement" << Space() << TokenizeType(VecType) << Space() |
| 3203 << GetBitcodeId(VecValue) << Comma() << FinishCluster() << Space() |
| 3204 << StartCluster() << TokenizeType(EltType) << Space() |
| 3205 << GetBitcodeId(EltValue) << Comma() << FinishCluster() << Space() |
| 3206 << StartCluster() << TokenizeType(IdxType) << Space() |
| 3207 << GetBitcodeId(IdxValue) << Semicolon() << FinishCluster(); |
| 3208 InstallInstType(VecType); |
| 3209 break; |
| 3210 } |
| 3211 case naclbitc::FUNC_CODE_INST_CALL: |
| 3212 case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: { |
| 3213 // CALL: [cc, fnid, arg0, arg1...] |
| 3214 // CALL_INDIRECT: [cc, fnid, returnty, args...] |
| 3215 if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) { |
| 3216 if (Values.size() < 2) { |
| 3217 Errors() << "Call record expects at least 2 arguments. Found: " |
| 3218 << Values.size() << "\n"; |
| 3219 break; |
| 3220 } |
| 3221 } else if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL_INDIRECT) { |
| 3222 if (Values.size() < 3) { |
| 3223 Errors() << "Call indirect record expects at least 3 arguments. Found: " |
| 3224 << Values.size() << "\n"; |
| 3225 break; |
| 3226 } |
| 3227 } |
| 3228 unsigned IsTailCall = (Values[0] & 0x1); |
| 3229 CallingConv::ID CallingConv; |
| 3230 uint32_t FcnId = RelativeToAbsId(Values[1]); |
| 3231 if (!naclbitc::DecodeCallingConv(Values[0]>>1, CallingConv)) |
| 3232 Errors() << "Call unknown calling convention:" << (Values[0]>>1) << "\n"; |
| 3233 if (!IgnorePNaClABIChecks && |
| 3234 !PNaClABIProps::isValidCallingConv(CallingConv)) { |
| 3235 Errors() << "Call uses disallowed calling convention: " |
| 3236 << PNaClABIProps::CallingConvName(CallingConv) << "(" |
| 3237 << CallingConv << ")\n"; |
| 3238 } |
| 3239 FunctionType *FcnType = 0; |
| 3240 Type *ReturnType = 0; |
| 3241 size_t ArgIndex = 2; |
| 3242 // Flag defining if type checking should be done on argument/return |
| 3243 // types. |
| 3244 bool CheckArgRetTypes = true; |
| 3245 if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) { |
| 3246 Type *FcnTy = GetFunctionValueType(FcnId); |
| 3247 if (FunctionType *FcnTyp = dyn_cast<FunctionType>(FcnTy)) { |
| 3248 // TODO(kschimpf) Add back signature checking once we know how |
| 3249 // to handle intrinsics (which can violate general signature |
| 3250 // rules). |
| 3251 CheckArgRetTypes = false; |
| 3252 FcnType = FcnTyp; |
| 3253 ReturnType = FcnType->getReturnType(); |
| 3254 } else { |
| 3255 Errors() << "Invalid function signature: " << *FcnTy << "\n"; |
| 3256 ReturnType = GetVoidType(); |
| 3257 } |
| 3258 } else { |
| 3259 ReturnType = GetType(Values[2]); |
| 3260 ArgIndex = 3; |
| 3261 } |
| 3262 if (!ReturnType->isVoidTy()) { |
| 3263 Tokens() << NextInstId() << Space() << "=" << Space(); |
| 3264 } |
| 3265 if (IsTailCall) { |
| 3266 Tokens() << "tail" << Space(); |
| 3267 } |
| 3268 if (CheckArgRetTypes && |
| 3269 !IgnorePNaClABIChecks && |
| 3270 !PNaClABITypeChecker::isValidParamType(ReturnType)) { |
| 3271 Errors() << "Invalid return type: " << *ReturnType << "\n"; |
| 3272 } |
| 3273 Tokens() << "call" << Space(); |
| 3274 if (CallingConv != CallingConv::C) { |
| 3275 Tokens() << PNaClABIProps::CallingConvName(CallingConv) << Space(); |
| 3276 } |
| 3277 Tokens() << TokenizeType(ReturnType) << Space() |
| 3278 << StartCluster() << GetBitcodeId(FcnId) << OpenParen() |
| 3279 << StartCluster(); |
| 3280 unsigned ParamIndex = 0; |
| 3281 unsigned NumParams = Values.size() + 1 - ArgIndex; |
| 3282 for (size_t i = ArgIndex; i < Values.size(); ++i, ++ParamIndex) { |
| 3283 uint32_t ParamId = RelativeToAbsId(Values[i]); |
| 3284 Type *ParamType = GetValueType(ParamId); |
| 3285 if (CheckArgRetTypes && |
| 3286 !IgnorePNaClABIChecks && |
| 3287 !PNaClABITypeChecker::isValidParamType(ParamType)) { |
| 3288 Errors() << "invalid type for parameter " << i << ": " |
| 3289 << *ParamType << "\n"; |
| 3290 } |
| 3291 if (FcnType) { |
| 3292 if (ParamIndex < FcnType->getNumParams()) { |
| 3293 Type *ExpectedType = FcnType->getParamType(ParamIndex); |
| 3294 if (ParamType != ExpectedType) { |
| 3295 Warnings() << "Parameter " << (ParamIndex + 1) << " mismatch: " |
| 3296 << *ParamType << " and " << *ExpectedType << "\n"; |
| 3297 } |
| 3298 } |
| 3299 else if (ParamIndex == FcnType->getNumParams()) { |
| 3300 Warnings() << "Call expects " << FcnType->getNumParams() |
| 3301 << " arguments. Got: " << NumParams << "\n"; |
| 3302 } |
| 3303 } |
| 3304 if (i > ArgIndex) { |
| 3305 Tokens() << Comma() << FinishCluster() << Space() << StartCluster(); |
| 3306 } |
| 3307 Tokens() << TokenizeType(ParamType) << Space() << GetBitcodeId(ParamId); |
| 3308 } |
| 3309 Tokens() << CloseParen() << Semicolon() << FinishCluster() |
| 3310 << FinishCluster(); |
| 3311 if (!ReturnType->isVoidTy()) InstallInstType(ReturnType); |
| 3312 break; |
| 3313 } |
| 3314 case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF: { |
| 3315 // TYPE: [opval, ty] |
| 3316 if (Values.size() != 2) { |
| 3317 Errors() << "Forward declare record expects 2 arguments. Found: " |
| 3318 << Values.size() << "\n"; |
| 3319 break; |
| 3320 } |
| 3321 Type *OpType = GetType(Values[1]); |
| 3322 Tokens() << "declare" << Space() << StartCluster() |
| 3323 << TokenizeType(OpType) << Space() |
| 3324 << GetBitcodeId(Values[0]) << Semicolon() << FinishCluster(); |
| 3325 InstallInstType(OpType, AbsToValuedInstId(Values[0])); |
| 3326 break; |
| 3327 } |
| 3328 default: |
| 3329 Errors() << "Unknown record found in module block.\n"; |
| 3330 break; |
| 3331 } |
| 3332 Tokens() << TokenizeAbbrevIndex() << Endline(); |
| 3333 ObjDumpWrite(Record.GetStartBit(), Record); |
| 3334 } |
| 3335 |
| 3336 /// Parses and disassembles the module block. |
| 3337 class NaClDisModuleParser : public NaClDisBlockParser { |
| 3338 public: |
| 3339 NaClDisModuleParser(unsigned BlockID, NaClDisTopLevelParser *Context) |
| 3340 : NaClDisBlockParser(BlockID, Context) { |
| 3341 } |
| 3342 |
| 3343 ~NaClDisModuleParser() override; |
| 3344 |
| 3345 bool ParseBlock(unsigned BlockID) override; |
| 3346 |
| 3347 void PrintBlockHeader() override; |
| 3348 |
| 3349 void ProcessRecord() override; |
| 3350 }; |
| 3351 |
| 3352 NaClDisModuleParser::~NaClDisModuleParser() { |
| 3353 // Note: Since we can't check type signatures of most functions till |
| 3354 // we know intrinsic names, and that isn't known until the (optional) |
| 3355 // valuesymtab block is parsed, the only reasonable spot to check |
| 3356 // function signatures is once the module block has been processed. |
| 3357 unsigned NextFcnDefinedId = 0; |
| 3358 for (unsigned i = 0, e = GetNumFunctions(); i < e; ++i) { |
| 3359 // Note: If the type of a function isn't a function type, that |
| 3360 // was checked in method ProcessRecord. |
| 3361 // Note: If the function was defined, the type was checked in |
| 3362 // NaClDisFunctionParser::PrintBlockHeader. |
| 3363 if (Context->HasDefinedFunctionIndex(NextFcnDefinedId) |
| 3364 && i == Context->GetDefinedFunctionIndex(NextFcnDefinedId)) { |
| 3365 ++NextFcnDefinedId; |
| 3366 continue; |
| 3367 } |
| 3368 if (FunctionType *FcnTy = dyn_cast<FunctionType>(GetFunctionValueType(i))) { |
| 3369 if (!Context->IsFunctionIntrinsic(i) && |
| 3370 !IgnorePNaClABIChecks && |
| 3371 !PNaClABITypeChecker::isValidFunctionType(FcnTy)) { |
| 3372 Context->SetRecordAddressToFunctionIdAddress(i); |
| 3373 Errors() << "Invalid type signature for " |
| 3374 << BitcodeId('f', i) << ": " << *FcnTy << "\n"; |
| 3375 } |
| 3376 } |
| 3377 } |
| 3378 } |
| 3379 |
| 3380 bool NaClDisModuleParser::ParseBlock(unsigned BlockID) { |
| 3381 ObjDumpSetRecordBitAddress(GetBlock().GetStartBit()); |
| 3382 switch (BlockID) { |
| 3383 case naclbitc::BLOCKINFO_BLOCK_ID: { |
| 3384 NaClDisBlockInfoParser Parser(BlockID, this); |
| 3385 return Parser.ParseThisBlock(); |
| 3386 } |
| 3387 case naclbitc::TYPE_BLOCK_ID_NEW: { |
| 3388 NaClDisTypesParser Parser(BlockID, this); |
| 3389 return Parser.ParseThisBlock(); |
| 3390 } |
| 3391 case naclbitc::GLOBALVAR_BLOCK_ID: { |
| 3392 NaClDisGlobalsParser Parser(BlockID, this); |
| 3393 return Parser.ParseThisBlock(); |
| 3394 } |
| 3395 case naclbitc::VALUE_SYMTAB_BLOCK_ID: { |
| 3396 NaClDisValueSymtabParser Parser(BlockID, this); |
| 3397 return Parser.ParseThisBlock(); |
| 3398 } |
| 3399 case naclbitc::FUNCTION_BLOCK_ID: { |
| 3400 NaClDisFunctionParser Parser(BlockID, this); |
| 3401 return Parser.ParseThisBlock(); |
| 3402 } |
| 3403 default: |
| 3404 return NaClDisBlockParser::ParseBlock(BlockID); |
| 3405 } |
| 3406 } |
| 3407 |
| 3408 void NaClDisModuleParser::PrintBlockHeader() { |
| 3409 Tokens() << "module" << Space() << OpenCurly() |
| 3410 << Space() << Space() << "// BlockID = " << GetBlockID() |
| 3411 << Endline(); |
| 3412 } |
| 3413 |
| 3414 void NaClDisModuleParser::ProcessRecord() { |
| 3415 ObjDumpSetRecordBitAddress(Record.GetStartBit()); |
| 3416 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
| 3417 switch (Record.GetCode()) { |
| 3418 case naclbitc::MODULE_CODE_VERSION: |
| 3419 // [version#] |
| 3420 if (Values.size() != 1) { |
| 3421 Errors() << "Version record should have one argument. Found: " |
| 3422 << Values.size() << "\n"; |
| 3423 break; |
| 3424 } |
| 3425 Tokens() << "version" << Space() << Values[0] << Semicolon() |
| 3426 << TokenizeAbbrevIndex() << Endline(); |
| 3427 break; |
| 3428 case naclbitc::MODULE_CODE_FUNCTION: { |
| 3429 // [type, callingconv, isproto, linkage] |
| 3430 if (Values.size() != 4) { |
| 3431 Errors() << "Function record should have 4 arguments. Found: " |
| 3432 << Values.size() << "\n"; |
| 3433 break; |
| 3434 } |
| 3435 bool IsProto = (Values[2] != 0); |
| 3436 Tokens() << StartCluster() << (IsProto ? "declare" : "define"); |
| 3437 uint32_t FcnId = GetNumFunctions(); |
| 3438 BitcodeId FcnName('f', FcnId); |
| 3439 std::string FcnStrName(FcnName.GetName()); |
| 3440 GlobalValue::LinkageTypes Linkage; |
| 3441 if (!naclbitc::DecodeLinkage(Values[3], Linkage)) { |
| 3442 Errors() << "Unknown linkage value: " << Values[3] << "\n"; |
| 3443 } else { |
| 3444 if (!IgnorePNaClABIChecks && |
| 3445 !PNaClABIProps::isValidGlobalLinkage(Linkage)) { |
| 3446 Errors() << "Disallowed linkage type: " |
| 3447 << PNaClABIProps::LinkageName(Linkage) << "\n"; |
| 3448 } |
| 3449 Tokens() << Space() << PNaClABIProps::LinkageName(Linkage); |
| 3450 } |
| 3451 CallingConv::ID CallingConv; |
| 3452 if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) { |
| 3453 Errors() << "Unknown calling convention value: " << Values[1] << "\n"; |
| 3454 } else if (PNaClABIProps::isValidCallingConv(CallingConv)) { |
| 3455 if (CallingConv != CallingConv::C) { |
| 3456 Tokens() << Space() << PNaClABIProps::CallingConvName(CallingConv); |
| 3457 } |
| 3458 } else { |
| 3459 Errors() << "Function " << FcnStrName |
| 3460 << " has disallowed calling convention: " |
| 3461 << PNaClABIProps::CallingConvName(CallingConv) |
| 3462 << " (" << CallingConv << ")\n"; |
| 3463 } |
| 3464 Tokens() << FinishCluster() << Space() << StartCluster(); |
| 3465 Type *FcnType = GetType(Values[0]); |
| 3466 FunctionType *FunctionTy = dyn_cast<FunctionType>(FcnType); |
| 3467 if (FunctionTy) { |
| 3468 Tokens() << TokenizeFunctionType(FunctionTy, &FcnName); |
| 3469 } else { |
| 3470 BitcodeId FcnTypeId('t', Values[0]); |
| 3471 Errors() << "Not function type: " << FcnTypeId << " = " |
| 3472 << *FcnType << "\n"; |
| 3473 Tokens() << "???"; |
| 3474 SmallVector<Type*, 1> Signature; |
| 3475 FunctionTy = FunctionType::get(GetVoidType(), Signature, 0); |
| 3476 } |
| 3477 Tokens() << Semicolon() << FinishCluster() << TokenizeAbbrevIndex() |
| 3478 << Endline(); |
| 3479 InstallFunctionType(FunctionTy); |
| 3480 if (!IsProto) InstallDefinedFunction(FcnId); |
| 3481 break; |
| 3482 } |
| 3483 default: |
| 3484 Errors() << "Unknown record found in module block\n"; |
| 3485 break; |
| 3486 } |
| 3487 ObjDumpWrite(Record.GetStartBit(), Record); |
| 3488 } |
| 3489 |
| 3490 bool NaClDisTopLevelParser::ParseBlock(unsigned BlockID) { |
| 3491 // Before parsing top-level module block. Describe header. |
| 3492 NaClBitcodeRecordData Record; |
| 3493 size_t HeaderSize = Header.getHeaderSize(); |
| 3494 Record.Code = naclbitc::BLK_CODE_HEADER; |
| 3495 for (size_t i = 0; i < HeaderSize; ++i) { |
| 3496 Record.Values.push_back(HeaderBuffer[i]); |
| 3497 } |
| 3498 if (ObjDump.GetDumpRecords() && ObjDump.GetDumpAssembly()) { |
| 3499 if (HeaderSize >= 4) { |
| 3500 const NaClRecordVector &Values = Record.Values; |
| 3501 Tokens() << "Magic" << Space() << "Number" << Colon() |
| 3502 << Space() << StartCluster() << StartCluster() << "'" |
| 3503 << (char) Values[0] << (char) Values[1] |
| 3504 << (char) Values[2] << (char) Values[3] |
| 3505 << "'" << FinishCluster() << Space() |
| 3506 << StartCluster() << OpenParen() |
| 3507 << Values[0] << Comma() << Space() |
| 3508 << Values[1] << Comma() << Space() |
| 3509 << Values[2] << Comma() << Space() |
| 3510 << Values[3] << CloseParen() << FinishCluster() |
| 3511 << FinishCluster() << Endline(); |
| 3512 } |
| 3513 // Show interpretation of header as assembly. |
| 3514 for (size_t i = 0; i < Header.NumberFields(); ++i) { |
| 3515 Tokens() << Header.GetField(i)->Contents() << Endline(); |
| 3516 } |
| 3517 } |
| 3518 ObjDump.Write(0, Record); |
| 3519 ObjDump.SetStartOffset(HeaderSize * 8); |
| 3520 |
| 3521 if (BlockID != naclbitc::MODULE_BLOCK_ID) |
| 3522 return Error("Module block expected at top-level, but not found"); |
| 3523 |
| 3524 // Now parse a module block. |
| 3525 NaClDisModuleParser Parser(BlockID, this); |
| 3526 return Parser.ParseThisBlock(); |
| 3527 } |
| 3528 |
| 3529 } |
| 3530 |
| 3531 namespace llvm { |
| 3532 |
| 3533 bool NaClObjDump(MemoryBuffer *MemBuf, raw_ostream &Output, |
| 3534 bool NoRecords, bool NoAssembly) { |
| 3535 // Create objects needed to run parser. |
| 3536 naclbitc::ObjDumpStream ObjDump(Output, !NoRecords, !NoAssembly); |
| 3537 |
| 3538 if (MemBuf->getBufferSize() % 4 != 0) { |
| 3539 ObjDump.Error() |
| 3540 << "Bitcode stream should be a multiple of 4 bytes in length.\n"; |
| 3541 return true; |
| 3542 } |
| 3543 |
| 3544 const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart(); |
| 3545 const unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize(); |
| 3546 const unsigned char *HeaderPtr = BufPtr; |
| 3547 |
| 3548 // Read header and verify it is good. |
| 3549 NaClBitcodeHeader Header; |
| 3550 if (Header.Read(BufPtr, EndBufPtr) || !Header.IsSupported()) { |
| 3551 ObjDump.Error() << "Invalid PNaCl bitcode header.\n"; |
| 3552 return true; |
| 3553 } |
| 3554 |
| 3555 // Create a bitstream reader to read the bitcode file. |
| 3556 NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr); |
| 3557 NaClBitstreamCursor InputStream(InputStreamFile); |
| 3558 |
| 3559 // Parse the the bitcode file. |
| 3560 ::NaClDisTopLevelParser Parser(Header, HeaderPtr, InputStream, ObjDump); |
| 3561 int NumBlocksRead = 0; |
| 3562 bool ErrorsFound = false; |
| 3563 while (!InputStream.AtEndOfStream()) { |
| 3564 ++NumBlocksRead; |
| 3565 if (Parser.Parse()) ErrorsFound = true; |
| 3566 } |
| 3567 |
| 3568 if (NumBlocksRead != 1) { |
| 3569 ObjDump.Error() << "Expected 1 top level block in bitcode: Found:" |
| 3570 << NumBlocksRead << "\n"; |
| 3571 ErrorsFound = true; |
| 3572 } |
| 3573 |
| 3574 ObjDump.Flush(); |
| 3575 return ErrorsFound || Parser.GetNumErrors() > 0; |
| 3576 } |
| 3577 |
| 3578 } |
OLD | NEW |