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

Side by Side Diff: lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp

Issue 14813032: Make abbreviations explicit in pnacl-freeze/thaw. (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Small cleanups suggested by Jan in CL. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- NaClBitcodeReader.cpp ----------------------------------------------===// 1 //===- NaClBitcodeReader.cpp ----------------------------------------------===//
2 // Internal NaClBitcodeReader implementation 2 // Internal NaClBitcodeReader implementation
3 // 3 //
4 // The LLVM Compiler Infrastructure 4 // The LLVM Compiler Infrastructure
5 // 5 //
6 // This file is distributed under the University of Illinois Open Source 6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details. 7 // License. See LICENSE.TXT for details.
8 // 8 //
9 //===----------------------------------------------------------------------===// 9 //===----------------------------------------------------------------------===//
10 10
11 #define DEBUG_TYPE "NaClBitcodeReader"
12
11 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" 13 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
12 #include "NaClBitcodeReader.h" 14 #include "NaClBitcodeReader.h"
13 #include "llvm/ADT/SmallString.h" 15 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/AutoUpgrade.h" 17 #include "llvm/AutoUpgrade.h"
16 #include "llvm/IR/Constants.h" 18 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/DerivedTypes.h"
18 #include "llvm/IR/InlineAsm.h" 20 #include "llvm/IR/InlineAsm.h"
19 #include "llvm/IR/IntrinsicInst.h" 21 #include "llvm/IR/IntrinsicInst.h"
20 #include "llvm/IR/Module.h" 22 #include "llvm/IR/Module.h"
21 #include "llvm/IR/OperandTraits.h" 23 #include "llvm/IR/OperandTraits.h"
22 #include "llvm/IR/Operator.h" 24 #include "llvm/IR/Operator.h"
25 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/DataStream.h" 26 #include "llvm/Support/DataStream.h"
24 #include "llvm/Support/MathExtras.h" 27 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Support/MemoryBuffer.h" 28 #include "llvm/Support/MemoryBuffer.h"
26 using namespace llvm; 29 using namespace llvm;
27 30
28 enum { 31 enum {
29 SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex 32 SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
30 }; 33 };
31 34
32 void NaClBitcodeReader::materializeForwardReferencedFunctions() { 35 void NaClBitcodeReader::materializeForwardReferencedFunctions() {
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 assert((!Alignment || isPowerOf2_32(Alignment)) && 446 assert((!Alignment || isPowerOf2_32(Alignment)) &&
444 "Alignment must be a power of two."); 447 "Alignment must be a power of two.");
445 448
446 if (Alignment) 449 if (Alignment)
447 B.addAlignmentAttr(Alignment); 450 B.addAlignmentAttr(Alignment);
448 B.addRawValue(((EncodedAttrs & (0xfffffULL << 32)) >> 11) | 451 B.addRawValue(((EncodedAttrs & (0xfffffULL << 32)) >> 11) |
449 (EncodedAttrs & 0xffff)); 452 (EncodedAttrs & 0xffff));
450 } 453 }
451 454
452 bool NaClBitcodeReader::ParseAttributeBlock() { 455 bool NaClBitcodeReader::ParseAttributeBlock() {
456 DEBUG(dbgs() << "-> ParseAttributeBlock\n");
453 if (Stream.EnterSubBlock(naclbitc::PARAMATTR_BLOCK_ID)) 457 if (Stream.EnterSubBlock(naclbitc::PARAMATTR_BLOCK_ID))
454 return Error("Malformed block record"); 458 return Error("Malformed block record");
455 459
456 if (!MAttributes.empty()) 460 if (!MAttributes.empty())
457 return Error("Multiple PARAMATTR blocks found!"); 461 return Error("Multiple PARAMATTR blocks found!");
458 462
459 SmallVector<uint64_t, 64> Record; 463 SmallVector<uint64_t, 64> Record;
460 464
461 SmallVector<AttributeSet, 8> Attrs; 465 SmallVector<AttributeSet, 8> Attrs;
462 466
463 // Read all the records. 467 // Read all the records.
464 while (1) { 468 while (1) {
465 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 469 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
466 470
467 switch (Entry.Kind) { 471 switch (Entry.Kind) {
468 case NaClBitstreamEntry::SubBlock: // Handled for us already. 472 case NaClBitstreamEntry::SubBlock: // Handled for us already.
469 case NaClBitstreamEntry::Error: 473 case NaClBitstreamEntry::Error:
470 return Error("Error at end of PARAMATTR block"); 474 return Error("Error at end of PARAMATTR block");
471 case NaClBitstreamEntry::EndBlock: 475 case NaClBitstreamEntry::EndBlock:
476 DEBUG(dbgs() << "<- ParseAttributeBlock\n");
472 return false; 477 return false;
473 case NaClBitstreamEntry::Record: 478 case NaClBitstreamEntry::Record:
474 // The interesting case. 479 // The interesting case.
475 break; 480 break;
476 } 481 }
477 482
478 // Read a record. 483 // Read a record.
479 Record.clear(); 484 Record.clear();
480 switch (Stream.readRecord(Entry.ID, Record)) { 485 switch (Stream.readRecord(Entry.ID, Record)) {
481 default: // Default behavior: ignore. 486 default: // Default behavior: ignore.
(...skipping 19 matching lines...) Expand all
501 506
502 MAttributes.push_back(AttributeSet::get(Context, Attrs)); 507 MAttributes.push_back(AttributeSet::get(Context, Attrs));
503 Attrs.clear(); 508 Attrs.clear();
504 break; 509 break;
505 } 510 }
506 } 511 }
507 } 512 }
508 } 513 }
509 514
510 bool NaClBitcodeReader::ParseAttributeGroupBlock() { 515 bool NaClBitcodeReader::ParseAttributeGroupBlock() {
516 DEBUG(dbgs() << "-> ParseAttributeGroupBlock\n");
511 if (Stream.EnterSubBlock(naclbitc::PARAMATTR_GROUP_BLOCK_ID)) 517 if (Stream.EnterSubBlock(naclbitc::PARAMATTR_GROUP_BLOCK_ID))
512 return Error("Malformed block record"); 518 return Error("Malformed block record");
513 519
514 if (!MAttributeGroups.empty()) 520 if (!MAttributeGroups.empty())
515 return Error("Multiple PARAMATTR_GROUP blocks found!"); 521 return Error("Multiple PARAMATTR_GROUP blocks found!");
516 522
517 SmallVector<uint64_t, 64> Record; 523 SmallVector<uint64_t, 64> Record;
518 524
519 // Read all the records. 525 // Read all the records.
520 while (1) { 526 while (1) {
521 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 527 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
522 528
523 switch (Entry.Kind) { 529 switch (Entry.Kind) {
524 case NaClBitstreamEntry::SubBlock: // Handled for us already. 530 case NaClBitstreamEntry::SubBlock: // Handled for us already.
525 case NaClBitstreamEntry::Error: 531 case NaClBitstreamEntry::Error:
526 return Error("Error at end of PARAMATTR_GROUP block"); 532 return Error("Error at end of PARAMATTR_GROUP block");
527 case NaClBitstreamEntry::EndBlock: 533 case NaClBitstreamEntry::EndBlock:
534 DEBUG(dbgs() << "<- ParseAttributeGroupBlock\n");
528 return false; 535 return false;
529 case NaClBitstreamEntry::Record: 536 case NaClBitstreamEntry::Record:
530 // The interesting case. 537 // The interesting case.
531 break; 538 break;
532 } 539 }
533 540
534 // Read a record. 541 // Read a record.
535 Record.clear(); 542 Record.clear();
536 switch (Stream.readRecord(Entry.ID, Record)) { 543 switch (Stream.readRecord(Entry.ID, Record)) {
537 default: // Default behavior: ignore. 544 default: // Default behavior: ignore.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 } 584 }
578 585
579 MAttributeGroups[GrpID] = AttributeSet::get(Context, Idx, B); 586 MAttributeGroups[GrpID] = AttributeSet::get(Context, Idx, B);
580 break; 587 break;
581 } 588 }
582 } 589 }
583 } 590 }
584 } 591 }
585 592
586 bool NaClBitcodeReader::ParseTypeTable() { 593 bool NaClBitcodeReader::ParseTypeTable() {
594 DEBUG(dbgs() << "-> ParseTypeTable\n");
587 if (Stream.EnterSubBlock(naclbitc::TYPE_BLOCK_ID_NEW)) 595 if (Stream.EnterSubBlock(naclbitc::TYPE_BLOCK_ID_NEW))
588 return Error("Malformed block record"); 596 return Error("Malformed block record");
589 597
590 return ParseTypeTableBody(); 598 bool result = ParseTypeTableBody();
599 if (!result)
600 DEBUG(dbgs() << "<- ParseTypeTable\n");
601 return result;
591 } 602 }
592 603
593 bool NaClBitcodeReader::ParseTypeTableBody() { 604 bool NaClBitcodeReader::ParseTypeTableBody() {
594 if (!TypeList.empty()) 605 if (!TypeList.empty())
595 return Error("Multiple TYPE_BLOCKs found!"); 606 return Error("Multiple TYPE_BLOCKs found!");
596 607
597 SmallVector<uint64_t, 64> Record; 608 SmallVector<uint64_t, 64> Record;
598 unsigned NumRecords = 0; 609 unsigned NumRecords = 0;
599 610
600 SmallString<64> TypeName; 611 SmallString<64> TypeName;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 814
804 if (NumRecords >= TypeList.size()) 815 if (NumRecords >= TypeList.size())
805 return Error("invalid TYPE table"); 816 return Error("invalid TYPE table");
806 assert(ResultTy && "Didn't read a type?"); 817 assert(ResultTy && "Didn't read a type?");
807 assert(TypeList[NumRecords] == 0 && "Already read type?"); 818 assert(TypeList[NumRecords] == 0 && "Already read type?");
808 TypeList[NumRecords++] = ResultTy; 819 TypeList[NumRecords++] = ResultTy;
809 } 820 }
810 } 821 }
811 822
812 bool NaClBitcodeReader::ParseValueSymbolTable() { 823 bool NaClBitcodeReader::ParseValueSymbolTable() {
824 DEBUG(dbgs() << "-> ParseValueSymbolTable\n");
813 if (Stream.EnterSubBlock(naclbitc::VALUE_SYMTAB_BLOCK_ID)) 825 if (Stream.EnterSubBlock(naclbitc::VALUE_SYMTAB_BLOCK_ID))
814 return Error("Malformed block record"); 826 return Error("Malformed block record");
815 827
816 SmallVector<uint64_t, 64> Record; 828 SmallVector<uint64_t, 64> Record;
817 829
818 // Read all the records for this value table. 830 // Read all the records for this value table.
819 SmallString<128> ValueName; 831 SmallString<128> ValueName;
820 while (1) { 832 while (1) {
821 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 833 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
822 834
823 switch (Entry.Kind) { 835 switch (Entry.Kind) {
824 case NaClBitstreamEntry::SubBlock: // Handled for us already. 836 case NaClBitstreamEntry::SubBlock: // Handled for us already.
825 case NaClBitstreamEntry::Error: 837 case NaClBitstreamEntry::Error:
826 return Error("malformed value symbol table block"); 838 return Error("malformed value symbol table block");
827 case NaClBitstreamEntry::EndBlock: 839 case NaClBitstreamEntry::EndBlock:
840 DEBUG(dbgs() << "<- ParseValueSymbolTable\n");
828 return false; 841 return false;
829 case NaClBitstreamEntry::Record: 842 case NaClBitstreamEntry::Record:
830 // The interesting case. 843 // The interesting case.
831 break; 844 break;
832 } 845 }
833 846
834 // Read a record. 847 // Read a record.
835 Record.clear(); 848 Record.clear();
836 switch (Stream.readRecord(Entry.ID, Record)) { 849 switch (Stream.readRecord(Entry.ID, Record)) {
837 default: // Default behavior: unknown type. 850 default: // Default behavior: unknown type.
(...skipping 21 matching lines...) Expand all
859 ValueName.clear(); 872 ValueName.clear();
860 break; 873 break;
861 } 874 }
862 } 875 }
863 } 876 }
864 } 877 }
865 878
866 bool NaClBitcodeReader::ParseMetadata() { 879 bool NaClBitcodeReader::ParseMetadata() {
867 unsigned NextMDValueNo = MDValueList.size(); 880 unsigned NextMDValueNo = MDValueList.size();
868 881
882 DEBUG(dbgs() << "-> ParseMetadata\n");
869 if (Stream.EnterSubBlock(naclbitc::METADATA_BLOCK_ID)) 883 if (Stream.EnterSubBlock(naclbitc::METADATA_BLOCK_ID))
870 return Error("Malformed block record"); 884 return Error("Malformed block record");
871 885
872 SmallVector<uint64_t, 64> Record; 886 SmallVector<uint64_t, 64> Record;
873 887
874 // Read all the records. 888 // Read all the records.
875 while (1) { 889 while (1) {
876 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 890 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
877 891
878 switch (Entry.Kind) { 892 switch (Entry.Kind) {
879 case NaClBitstreamEntry::SubBlock: // Handled for us already. 893 case NaClBitstreamEntry::SubBlock: // Handled for us already.
880 case NaClBitstreamEntry::Error: 894 case NaClBitstreamEntry::Error:
881 Error("malformed metadata block"); 895 Error("malformed metadata block");
882 return true; 896 return true;
883 case NaClBitstreamEntry::EndBlock: 897 case NaClBitstreamEntry::EndBlock:
898 DEBUG(dbgs() << "<- ParseMetadata\n");
884 return false; 899 return false;
885 case NaClBitstreamEntry::Record: 900 case NaClBitstreamEntry::Record:
886 // The interesting case. 901 // The interesting case.
887 break; 902 break;
888 } 903 }
889 904
890 bool IsFunctionLocal = false; 905 bool IsFunctionLocal = false;
891 // Read a record. 906 // Read a record.
892 Record.clear(); 907 Record.clear();
893 unsigned Code = Stream.readRecord(Entry.ID, Record); 908 unsigned Code = Stream.readRecord(Entry.ID, Record);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 969
955 unsigned NewKind = TheModule->getMDKindID(Name.str()); 970 unsigned NewKind = TheModule->getMDKindID(Name.str());
956 if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second) 971 if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
957 return Error("Conflicting METADATA_KIND records"); 972 return Error("Conflicting METADATA_KIND records");
958 break; 973 break;
959 } 974 }
960 } 975 }
961 } 976 }
962 } 977 }
963 978
964 /// decodeSignRotatedValue - Decode a signed value stored with the sign bit in
965 /// the LSB for dense VBR encoding.
966 uint64_t NaClBitcodeReader::decodeSignRotatedValue(uint64_t V) {
967 if ((V & 1) == 0)
968 return V >> 1;
969 if (V != 1)
970 return -(V >> 1);
971 // There is no such thing as -0 with integers. "-0" really means MININT.
972 return 1ULL << 63;
973 }
974
975 /// ResolveGlobalAndAliasInits - Resolve all of the initializers for global 979 /// ResolveGlobalAndAliasInits - Resolve all of the initializers for global
976 /// values and aliases that we can. 980 /// values and aliases that we can.
977 bool NaClBitcodeReader::ResolveGlobalAndAliasInits() { 981 bool NaClBitcodeReader::ResolveGlobalAndAliasInits() {
978 std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist; 982 std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
979 std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist; 983 std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
980 984
981 GlobalInitWorklist.swap(GlobalInits); 985 GlobalInitWorklist.swap(GlobalInits);
982 AliasInitWorklist.swap(AliasInits); 986 AliasInitWorklist.swap(AliasInits);
983 987
984 while (!GlobalInitWorklist.empty()) { 988 while (!GlobalInitWorklist.empty()) {
(...skipping 21 matching lines...) Expand all
1006 return Error("Alias initializer is not a constant!"); 1010 return Error("Alias initializer is not a constant!");
1007 } 1011 }
1008 AliasInitWorklist.pop_back(); 1012 AliasInitWorklist.pop_back();
1009 } 1013 }
1010 return false; 1014 return false;
1011 } 1015 }
1012 1016
1013 static APInt ReadWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) { 1017 static APInt ReadWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
1014 SmallVector<uint64_t, 8> Words(Vals.size()); 1018 SmallVector<uint64_t, 8> Words(Vals.size());
1015 std::transform(Vals.begin(), Vals.end(), Words.begin(), 1019 std::transform(Vals.begin(), Vals.end(), Words.begin(),
1016 NaClBitcodeReader::decodeSignRotatedValue); 1020 NaClDecodeSignRotatedValue);
1017 1021
1018 return APInt(TypeBits, Words); 1022 return APInt(TypeBits, Words);
1019 } 1023 }
1020 1024
1021 bool NaClBitcodeReader::ParseConstants() { 1025 bool NaClBitcodeReader::ParseConstants() {
1026 DEBUG(dbgs() << "-> ParseConstants\n");
1022 if (Stream.EnterSubBlock(naclbitc::CONSTANTS_BLOCK_ID)) 1027 if (Stream.EnterSubBlock(naclbitc::CONSTANTS_BLOCK_ID))
1023 return Error("Malformed block record"); 1028 return Error("Malformed block record");
1024 1029
1025 SmallVector<uint64_t, 64> Record; 1030 SmallVector<uint64_t, 64> Record;
1026 1031
1027 // Read all the records for this value table. 1032 // Read all the records for this value table.
1028 Type *CurTy = Type::getInt32Ty(Context); 1033 Type *CurTy = Type::getInt32Ty(Context);
1029 unsigned NextCstNo = ValueList.size(); 1034 unsigned NextCstNo = ValueList.size();
1030 while (1) { 1035 while (1) {
1031 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 1036 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
1032 1037
1033 switch (Entry.Kind) { 1038 switch (Entry.Kind) {
1034 case NaClBitstreamEntry::SubBlock: // Handled for us already. 1039 case NaClBitstreamEntry::SubBlock: // Handled for us already.
1035 case NaClBitstreamEntry::Error: 1040 case NaClBitstreamEntry::Error:
1036 return Error("malformed block record in AST file"); 1041 return Error("malformed block record in AST file");
1037 case NaClBitstreamEntry::EndBlock: 1042 case NaClBitstreamEntry::EndBlock:
1038 if (NextCstNo != ValueList.size()) 1043 if (NextCstNo != ValueList.size())
1039 return Error("Invalid constant reference!"); 1044 return Error("Invalid constant reference!");
1040 1045
1041 // Once all the constants have been read, go through and resolve forward 1046 // Once all the constants have been read, go through and resolve forward
1042 // references. 1047 // references.
1043 ValueList.ResolveConstantForwardRefs(); 1048 ValueList.ResolveConstantForwardRefs();
1049 DEBUG(dbgs() << "<- ParseConstants\n");
1044 return false; 1050 return false;
1045 case NaClBitstreamEntry::Record: 1051 case NaClBitstreamEntry::Record:
1046 // The interesting case. 1052 // The interesting case.
1047 break; 1053 break;
1048 } 1054 }
1049 1055
1050 // Read a record. 1056 // Read a record.
1051 Record.clear(); 1057 Record.clear();
1052 Value *V = 0; 1058 Value *V = 0;
1053 unsigned BitCode = Stream.readRecord(Entry.ID, Record); 1059 unsigned BitCode = Stream.readRecord(Entry.ID, Record);
1054 switch (BitCode) { 1060 switch (BitCode) {
1055 default: // Default behavior: unknown constant 1061 default: // Default behavior: unknown constant
1056 case naclbitc::CST_CODE_UNDEF: // UNDEF 1062 case naclbitc::CST_CODE_UNDEF: // UNDEF
1057 V = UndefValue::get(CurTy); 1063 V = UndefValue::get(CurTy);
1058 break; 1064 break;
1059 case naclbitc::CST_CODE_SETTYPE: // SETTYPE: [typeid] 1065 case naclbitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
1060 if (Record.empty()) 1066 if (Record.empty())
1061 return Error("Malformed CST_SETTYPE record"); 1067 return Error("Malformed CST_SETTYPE record");
1062 if (Record[0] >= TypeList.size()) 1068 if (Record[0] >= TypeList.size())
1063 return Error("Invalid Type ID in CST_SETTYPE record"); 1069 return Error("Invalid Type ID in CST_SETTYPE record");
1064 CurTy = TypeList[Record[0]]; 1070 CurTy = TypeList[Record[0]];
1065 continue; // Skip the ValueList manipulation. 1071 continue; // Skip the ValueList manipulation.
1066 case naclbitc::CST_CODE_NULL: // NULL 1072 case naclbitc::CST_CODE_NULL: // NULL
1067 V = Constant::getNullValue(CurTy); 1073 V = Constant::getNullValue(CurTy);
1068 break; 1074 break;
1069 case naclbitc::CST_CODE_INTEGER: // INTEGER: [intval] 1075 case naclbitc::CST_CODE_INTEGER: // INTEGER: [intval]
1070 if (!CurTy->isIntegerTy() || Record.empty()) 1076 if (!CurTy->isIntegerTy() || Record.empty())
1071 return Error("Invalid CST_INTEGER record"); 1077 return Error("Invalid CST_INTEGER record");
1072 V = ConstantInt::get(CurTy, decodeSignRotatedValue(Record[0])); 1078 V = ConstantInt::get(CurTy, NaClDecodeSignRotatedValue(Record[0]));
1073 break; 1079 break;
1074 case naclbitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval] 1080 case naclbitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
1075 if (!CurTy->isIntegerTy() || Record.empty()) 1081 if (!CurTy->isIntegerTy() || Record.empty())
1076 return Error("Invalid WIDE_INTEGER record"); 1082 return Error("Invalid WIDE_INTEGER record");
1077 1083
1078 APInt VInt = ReadWideAPInt(Record, 1084 APInt VInt = ReadWideAPInt(Record,
1079 cast<IntegerType>(CurTy)->getBitWidth()); 1085 cast<IntegerType>(CurTy)->getBitWidth());
1080 V = ConstantInt::get(Context, VInt); 1086 V = ConstantInt::get(Context, VInt);
1081 1087
1082 break; 1088 break;
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 break; 1414 break;
1409 } 1415 }
1410 } 1416 }
1411 1417
1412 ValueList.AssignValue(V, NextCstNo); 1418 ValueList.AssignValue(V, NextCstNo);
1413 ++NextCstNo; 1419 ++NextCstNo;
1414 } 1420 }
1415 } 1421 }
1416 1422
1417 bool NaClBitcodeReader::ParseUseLists() { 1423 bool NaClBitcodeReader::ParseUseLists() {
1424 DEBUG(dbgs() << "-> ParseUseLists\n");
1418 if (Stream.EnterSubBlock(naclbitc::USELIST_BLOCK_ID)) 1425 if (Stream.EnterSubBlock(naclbitc::USELIST_BLOCK_ID))
1419 return Error("Malformed block record"); 1426 return Error("Malformed block record");
1420 1427
1421 SmallVector<uint64_t, 64> Record; 1428 SmallVector<uint64_t, 64> Record;
1422 1429
1423 // Read all the records. 1430 // Read all the records.
1424 while (1) { 1431 while (1) {
1425 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 1432 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
1426 1433
1427 switch (Entry.Kind) { 1434 switch (Entry.Kind) {
1428 case NaClBitstreamEntry::SubBlock: // Handled for us already. 1435 case NaClBitstreamEntry::SubBlock: // Handled for us already.
1429 case NaClBitstreamEntry::Error: 1436 case NaClBitstreamEntry::Error:
1430 return Error("malformed use list block"); 1437 return Error("malformed use list block");
1431 case NaClBitstreamEntry::EndBlock: 1438 case NaClBitstreamEntry::EndBlock:
1439 DEBUG(dbgs() << "<- ParseUseLists\n");
1432 return false; 1440 return false;
1433 case NaClBitstreamEntry::Record: 1441 case NaClBitstreamEntry::Record:
1434 // The interesting case. 1442 // The interesting case.
1435 break; 1443 break;
1436 } 1444 }
1437 1445
1438 // Read a use list record. 1446 // Read a use list record.
1439 Record.clear(); 1447 Record.clear();
1440 switch (Stream.readRecord(Entry.ID, Record)) { 1448 switch (Stream.readRecord(Entry.ID, Record)) {
1441 default: // Default behavior: unknown type. 1449 default: // Default behavior: unknown type.
1442 break; 1450 break;
1443 case naclbitc::USELIST_CODE_ENTRY: { // USELIST_CODE_ENTRY: TBD. 1451 case naclbitc::USELIST_CODE_ENTRY: { // USELIST_CODE_ENTRY: TBD.
1444 unsigned RecordLength = Record.size(); 1452 unsigned RecordLength = Record.size();
1445 if (RecordLength < 1) 1453 if (RecordLength < 1)
1446 return Error ("Invalid UseList reader!"); 1454 return Error ("Invalid UseList reader!");
1447 UseListRecords.push_back(Record); 1455 UseListRecords.push_back(Record);
1448 break; 1456 break;
1449 } 1457 }
1450 } 1458 }
1451 } 1459 }
1452 } 1460 }
1453 1461
1454 /// RememberAndSkipFunctionBody - When we see the block for a function body, 1462 /// RememberAndSkipFunctionBody - When we see the block for a function body,
1455 /// remember where it is and then skip it. This lets us lazily deserialize the 1463 /// remember where it is and then skip it. This lets us lazily deserialize the
1456 /// functions. 1464 /// functions.
1457 bool NaClBitcodeReader::RememberAndSkipFunctionBody() { 1465 bool NaClBitcodeReader::RememberAndSkipFunctionBody() {
1466 DEBUG(dbgs() << "-> RememberAndSkipFunctionBody\n");
1458 // Get the function we are talking about. 1467 // Get the function we are talking about.
1459 if (FunctionsWithBodies.empty()) 1468 if (FunctionsWithBodies.empty())
1460 return Error("Insufficient function protos"); 1469 return Error("Insufficient function protos");
1461 1470
1462 Function *Fn = FunctionsWithBodies.back(); 1471 Function *Fn = FunctionsWithBodies.back();
1463 FunctionsWithBodies.pop_back(); 1472 FunctionsWithBodies.pop_back();
1464 1473
1465 // Save the current stream state. 1474 // Save the current stream state.
1466 uint64_t CurBit = Stream.GetCurrentBitNo(); 1475 uint64_t CurBit = Stream.GetCurrentBitNo();
1467 DeferredFunctionInfo[Fn] = CurBit; 1476 DeferredFunctionInfo[Fn] = CurBit;
1468 1477
1469 // Skip over the function block for now. 1478 // Skip over the function block for now.
1470 if (Stream.SkipBlock()) 1479 if (Stream.SkipBlock())
1471 return Error("Malformed block record"); 1480 return Error("Malformed block record");
1481 DEBUG(dbgs() << "<- RememberAndSkipFunctionBody\n");
1472 return false; 1482 return false;
1473 } 1483 }
1474 1484
1475 bool NaClBitcodeReader::GlobalCleanup() { 1485 bool NaClBitcodeReader::GlobalCleanup() {
1476 // Patch the initializers for globals and aliases up. 1486 // Patch the initializers for globals and aliases up.
1477 ResolveGlobalAndAliasInits(); 1487 ResolveGlobalAndAliasInits();
1478 if (!GlobalInits.empty() || !AliasInits.empty()) 1488 if (!GlobalInits.empty() || !AliasInits.empty())
1479 return Error("Malformed global initializer set"); 1489 return Error("Malformed global initializer set");
1480 1490
1481 // Look for intrinsic functions which need to be upgraded at some point 1491 // Look for intrinsic functions which need to be upgraded at some point
(...skipping 10 matching lines...) Expand all
1492 GI != GE; ++GI) 1502 GI != GE; ++GI)
1493 UpgradeGlobalVariable(GI); 1503 UpgradeGlobalVariable(GI);
1494 // Force deallocation of memory for these vectors to favor the client that 1504 // Force deallocation of memory for these vectors to favor the client that
1495 // want lazy deserialization. 1505 // want lazy deserialization.
1496 std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits); 1506 std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
1497 std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits); 1507 std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
1498 return false; 1508 return false;
1499 } 1509 }
1500 1510
1501 bool NaClBitcodeReader::ParseModule(bool Resume) { 1511 bool NaClBitcodeReader::ParseModule(bool Resume) {
1512 DEBUG(dbgs() << "-> ParseModule\n");
1502 if (Resume) 1513 if (Resume)
1503 Stream.JumpToBit(NextUnreadBit); 1514 Stream.JumpToBit(NextUnreadBit);
1504 else if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID)) 1515 else if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID))
1505 return Error("Malformed block record"); 1516 return Error("Malformed block record");
1506 1517
1507 SmallVector<uint64_t, 64> Record; 1518 SmallVector<uint64_t, 64> Record;
1508 std::vector<std::string> SectionTable; 1519 std::vector<std::string> SectionTable;
1509 std::vector<std::string> GCTable; 1520 std::vector<std::string> GCTable;
1510 1521
1511 // Read all the records for this module. 1522 // Read all the records for this module.
1512 while (1) { 1523 while (1) {
1513 NaClBitstreamEntry Entry = Stream.advance(); 1524 NaClBitstreamEntry Entry = Stream.advance();
1514 1525
1515 switch (Entry.Kind) { 1526 switch (Entry.Kind) {
1516 case NaClBitstreamEntry::Error: 1527 case NaClBitstreamEntry::Error:
1517 Error("malformed module block"); 1528 Error("malformed module block");
1518 return true; 1529 return true;
1519 case NaClBitstreamEntry::EndBlock: 1530 case NaClBitstreamEntry::EndBlock:
1531 DEBUG(dbgs() << "<- ParseModule\n");
1520 return GlobalCleanup(); 1532 return GlobalCleanup();
1521 1533
1522 case NaClBitstreamEntry::SubBlock: 1534 case NaClBitstreamEntry::SubBlock:
1523 switch (Entry.ID) { 1535 switch (Entry.ID) {
1524 default: // Skip unknown content. 1536 default: // Skip unknown content.
1537 DEBUG(dbgs() << "Skip unknown context\n");
1525 if (Stream.SkipBlock()) 1538 if (Stream.SkipBlock())
1526 return Error("Malformed block record"); 1539 return Error("Malformed block record");
1527 break; 1540 break;
1528 case naclbitc::BLOCKINFO_BLOCK_ID: 1541 case naclbitc::BLOCKINFO_BLOCK_ID:
1529 if (Stream.ReadBlockInfoBlock()) 1542 if (Stream.ReadBlockInfoBlock())
1530 return Error("Malformed BlockInfoBlock"); 1543 return Error("Malformed BlockInfoBlock");
1531 break; 1544 break;
1532 case naclbitc::PARAMATTR_BLOCK_ID: 1545 case naclbitc::PARAMATTR_BLOCK_ID:
1533 if (ParseAttributeBlock()) 1546 if (ParseAttributeBlock())
1534 return true; 1547 return true;
(...skipping 24 matching lines...) Expand all
1559 // FunctionsWithBodies list. 1572 // FunctionsWithBodies list.
1560 if (!SeenFirstFunctionBody) { 1573 if (!SeenFirstFunctionBody) {
1561 std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end()); 1574 std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
1562 if (GlobalCleanup()) 1575 if (GlobalCleanup())
1563 return true; 1576 return true;
1564 SeenFirstFunctionBody = true; 1577 SeenFirstFunctionBody = true;
1565 } 1578 }
1566 1579
1567 if (RememberAndSkipFunctionBody()) 1580 if (RememberAndSkipFunctionBody())
1568 return true; 1581 return true;
1582
1569 // For streaming bitcode, suspend parsing when we reach the function 1583 // For streaming bitcode, suspend parsing when we reach the function
1570 // bodies. Subsequent materialization calls will resume it when 1584 // bodies. Subsequent materialization calls will resume it when
1571 // necessary. For streaming, the function bodies must be at the end of 1585 // necessary. For streaming, the function bodies must be at the end of
1572 // the bitcode. If the bitcode file is old, the symbol table will be 1586 // the bitcode. If the bitcode file is old, the symbol table will be
1573 // at the end instead and will not have been seen yet. In this case, 1587 // at the end instead and will not have been seen yet. In this case,
1574 // just finish the parse now. 1588 // just finish the parse now.
1575 if (LazyStreamer && SeenValueSymbolTable) { 1589 if (LazyStreamer && SeenValueSymbolTable) {
1576 NextUnreadBit = Stream.GetCurrentBitNo(); 1590 NextUnreadBit = Stream.GetCurrentBitNo();
1591 DEBUG(dbgs() << "<- ParseModule\n");
1577 return false; 1592 return false;
1578 } 1593 }
1579 break; 1594 break;
1580 case naclbitc::USELIST_BLOCK_ID: 1595 case naclbitc::USELIST_BLOCK_ID:
1581 if (ParseUseLists()) 1596 if (ParseUseLists())
1582 return true; 1597 return true;
1583 break; 1598 break;
1584 } 1599 }
1585 continue; 1600 continue;
1586 1601
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a && 1869 Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a &&
1855 Stream.AtEndOfStream()) 1870 Stream.AtEndOfStream())
1856 return false; 1871 return false;
1857 1872
1858 return Error("Invalid record at top-level"); 1873 return Error("Invalid record at top-level");
1859 } 1874 }
1860 } 1875 }
1861 } 1876 }
1862 1877
1863 bool NaClBitcodeReader::ParseModuleTriple(std::string &Triple) { 1878 bool NaClBitcodeReader::ParseModuleTriple(std::string &Triple) {
1879 DEBUG(dbgs() << "-> ParseModuleTriple\n");
1864 if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID)) 1880 if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID))
1865 return Error("Malformed block record"); 1881 return Error("Malformed block record");
1866 1882
1867 SmallVector<uint64_t, 64> Record; 1883 SmallVector<uint64_t, 64> Record;
1868 1884
1869 // Read all the records for this module. 1885 // Read all the records for this module.
1870 while (1) { 1886 while (1) {
1871 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 1887 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
1872 1888
1873 switch (Entry.Kind) { 1889 switch (Entry.Kind) {
1874 case NaClBitstreamEntry::SubBlock: // Handled for us already. 1890 case NaClBitstreamEntry::SubBlock: // Handled for us already.
1875 case NaClBitstreamEntry::Error: 1891 case NaClBitstreamEntry::Error:
1876 return Error("malformed module block"); 1892 return Error("malformed module block");
1877 case NaClBitstreamEntry::EndBlock: 1893 case NaClBitstreamEntry::EndBlock:
1894 DEBUG(dbgs() << "<- ParseModuleTriple\n");
1878 return false; 1895 return false;
1879 case NaClBitstreamEntry::Record: 1896 case NaClBitstreamEntry::Record:
1880 // The interesting case. 1897 // The interesting case.
1881 break; 1898 break;
1882 } 1899 }
1883 1900
1884 // Read a record. 1901 // Read a record.
1885 switch (Stream.readRecord(Entry.ID, Record)) { 1902 switch (Stream.readRecord(Entry.ID, Record)) {
1886 default: break; // Default behavior, ignore unknown content. 1903 default: break; // Default behavior, ignore unknown content.
1887 case naclbitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] 1904 case naclbitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 1950
1934 case NaClBitstreamEntry::Record: 1951 case NaClBitstreamEntry::Record:
1935 Stream.skipRecord(Entry.ID); 1952 Stream.skipRecord(Entry.ID);
1936 continue; 1953 continue;
1937 } 1954 }
1938 } 1955 }
1939 } 1956 }
1940 1957
1941 /// ParseMetadataAttachment - Parse metadata attachments. 1958 /// ParseMetadataAttachment - Parse metadata attachments.
1942 bool NaClBitcodeReader::ParseMetadataAttachment() { 1959 bool NaClBitcodeReader::ParseMetadataAttachment() {
1960 DEBUG(dbgs() << "-> ParseMetadataAttachment\n");
1943 if (Stream.EnterSubBlock(naclbitc::METADATA_ATTACHMENT_ID)) 1961 if (Stream.EnterSubBlock(naclbitc::METADATA_ATTACHMENT_ID))
1944 return Error("Malformed block record"); 1962 return Error("Malformed block record");
1945 1963
1946 SmallVector<uint64_t, 64> Record; 1964 SmallVector<uint64_t, 64> Record;
1947 while (1) { 1965 while (1) {
1948 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 1966 NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
1949 1967
1950 switch (Entry.Kind) { 1968 switch (Entry.Kind) {
1951 case NaClBitstreamEntry::SubBlock: // Handled for us already. 1969 case NaClBitstreamEntry::SubBlock: // Handled for us already.
1952 case NaClBitstreamEntry::Error: 1970 case NaClBitstreamEntry::Error:
1953 return Error("malformed metadata block"); 1971 return Error("malformed metadata block");
1954 case NaClBitstreamEntry::EndBlock: 1972 case NaClBitstreamEntry::EndBlock:
1973 DEBUG(dbgs() << "<- ParseMetadataAttachment\n");
1955 return false; 1974 return false;
1956 case NaClBitstreamEntry::Record: 1975 case NaClBitstreamEntry::Record:
1957 // The interesting case. 1976 // The interesting case.
1958 break; 1977 break;
1959 } 1978 }
1960 1979
1961 // Read a metadata attachment record. 1980 // Read a metadata attachment record.
1962 Record.clear(); 1981 Record.clear();
1963 switch (Stream.readRecord(Entry.ID, Record)) { 1982 switch (Stream.readRecord(Entry.ID, Record)) {
1964 default: // Default behavior: ignore. 1983 default: // Default behavior: ignore.
(...skipping 13 matching lines...) Expand all
1978 Inst->setMetadata(I->second, cast<MDNode>(Node)); 1997 Inst->setMetadata(I->second, cast<MDNode>(Node));
1979 } 1998 }
1980 break; 1999 break;
1981 } 2000 }
1982 } 2001 }
1983 } 2002 }
1984 } 2003 }
1985 2004
1986 /// ParseFunctionBody - Lazily parse the specified function body block. 2005 /// ParseFunctionBody - Lazily parse the specified function body block.
1987 bool NaClBitcodeReader::ParseFunctionBody(Function *F) { 2006 bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
2007 DEBUG(dbgs() << "-> ParseFunctionBody\n");
1988 if (Stream.EnterSubBlock(naclbitc::FUNCTION_BLOCK_ID)) 2008 if (Stream.EnterSubBlock(naclbitc::FUNCTION_BLOCK_ID))
1989 return Error("Malformed block record"); 2009 return Error("Malformed block record");
1990 2010
1991 InstructionList.clear(); 2011 InstructionList.clear();
1992 unsigned ModuleValueListSize = ValueList.size(); 2012 unsigned ModuleValueListSize = ValueList.size();
1993 unsigned ModuleMDValueListSize = MDValueList.size(); 2013 unsigned ModuleMDValueListSize = MDValueList.size();
1994 2014
1995 // Add all the function arguments to the value table. 2015 // Add all the function arguments to the value table.
1996 for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) 2016 for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
1997 ValueList.push_back(I); 2017 ValueList.push_back(I);
(...skipping 11 matching lines...) Expand all
2009 2029
2010 switch (Entry.Kind) { 2030 switch (Entry.Kind) {
2011 case NaClBitstreamEntry::Error: 2031 case NaClBitstreamEntry::Error:
2012 return Error("Bitcode error in function block"); 2032 return Error("Bitcode error in function block");
2013 case NaClBitstreamEntry::EndBlock: 2033 case NaClBitstreamEntry::EndBlock:
2014 goto OutOfRecordLoop; 2034 goto OutOfRecordLoop;
2015 2035
2016 case NaClBitstreamEntry::SubBlock: 2036 case NaClBitstreamEntry::SubBlock:
2017 switch (Entry.ID) { 2037 switch (Entry.ID) {
2018 default: // Skip unknown content. 2038 default: // Skip unknown content.
2039 dbgs() << "default skip block\n";
2019 if (Stream.SkipBlock()) 2040 if (Stream.SkipBlock())
2020 return Error("Malformed block record"); 2041 return Error("Malformed block record");
2021 break; 2042 break;
2022 case naclbitc::CONSTANTS_BLOCK_ID: 2043 case naclbitc::CONSTANTS_BLOCK_ID:
2023 if (ParseConstants()) return true; 2044 if (ParseConstants())
2045 return true;
2024 NextValueNo = ValueList.size(); 2046 NextValueNo = ValueList.size();
2025 break; 2047 break;
2026 case naclbitc::VALUE_SYMTAB_BLOCK_ID: 2048 case naclbitc::VALUE_SYMTAB_BLOCK_ID:
2027 if (ParseValueSymbolTable()) return true; 2049 if (ParseValueSymbolTable())
2050 return true;
2028 break; 2051 break;
2029 case naclbitc::METADATA_ATTACHMENT_ID: 2052 case naclbitc::METADATA_ATTACHMENT_ID:
2030 if (ParseMetadataAttachment()) return true; 2053 if (ParseMetadataAttachment())
2054 return true;
2031 break; 2055 break;
2032 case naclbitc::METADATA_BLOCK_ID: 2056 case naclbitc::METADATA_BLOCK_ID:
2033 if (ParseMetadata()) return true; 2057 if (ParseMetadata())
2058 return true;
2034 break; 2059 break;
2035 } 2060 }
2036 continue; 2061 continue;
2037 2062
2038 case NaClBitstreamEntry::Record: 2063 case NaClBitstreamEntry::Record:
2039 // The interesting case. 2064 // The interesting case.
2040 break; 2065 break;
2041 } 2066 }
2042 2067
2043 // Read a record. 2068 // Read a record.
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
2855 FwdRef->eraseFromParent(); 2880 FwdRef->eraseFromParent();
2856 } 2881 }
2857 2882
2858 BlockAddrFwdRefs.erase(BAFRI); 2883 BlockAddrFwdRefs.erase(BAFRI);
2859 } 2884 }
2860 2885
2861 // Trim the value list down to the size it was before we parsed this function. 2886 // Trim the value list down to the size it was before we parsed this function.
2862 ValueList.shrinkTo(ModuleValueListSize); 2887 ValueList.shrinkTo(ModuleValueListSize);
2863 MDValueList.shrinkTo(ModuleMDValueListSize); 2888 MDValueList.shrinkTo(ModuleMDValueListSize);
2864 std::vector<BasicBlock*>().swap(FunctionBBs); 2889 std::vector<BasicBlock*>().swap(FunctionBBs);
2890 DEBUG(dbgs() << "-> ParseFunctionBody\n");
2865 return false; 2891 return false;
2866 } 2892 }
2867 2893
2868 /// FindFunctionInStream - Find the function body in the bitcode stream 2894 /// FindFunctionInStream - Find the function body in the bitcode stream
2869 bool NaClBitcodeReader::FindFunctionInStream(Function *F, 2895 bool NaClBitcodeReader::FindFunctionInStream(Function *F,
2870 DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) { 2896 DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) {
2871 while (DeferredFunctionInfoIterator->second == 0) { 2897 while (DeferredFunctionInfoIterator->second == 0) {
2872 if (Stream.AtEndOfStream()) 2898 if (Stream.AtEndOfStream())
2873 return Error("Could not find Function in stream"); 2899 return Error("Could not find Function in stream");
2874 // ParseModule will parse the next body in the stream and set its 2900 // ParseModule will parse the next body in the stream and set its
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
3115 if (M->MaterializeAllPermanently(ErrMsg)) { 3141 if (M->MaterializeAllPermanently(ErrMsg)) {
3116 delete M; 3142 delete M;
3117 return 0; 3143 return 0;
3118 } 3144 }
3119 3145
3120 // TODO: Restore the use-lists to the in-memory state when the bitcode was 3146 // TODO: Restore the use-lists to the in-memory state when the bitcode was
3121 // written. We must defer until the Module has been fully materialized. 3147 // written. We must defer until the Module has been fully materialized.
3122 3148
3123 return M; 3149 return M;
3124 } 3150 }
OLDNEW
« no previous file with comments | « lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h ('k') | lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698