Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 1 | //===- Parser.cpp - Code to parse bytecode files --------------------------===// |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 10 | // This library implements the functionality defined in llvm/Bytecode/Parser.h |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 11 | // |
| 12 | // Note that this library should be as fast as possible, reentrant, and |
| 13 | // threadsafe!! |
| 14 | // |
| 15 | // TODO: Allow passing in an option to ignore the symbol table |
| 16 | // |
| 17 | //===----------------------------------------------------------------------===// |
| 18 | |
| 19 | #include "AnalyzerInternals.h" |
| 20 | #include "llvm/Module.h" |
| 21 | #include "llvm/Bytecode/Format.h" |
| 22 | #include "Support/StringExtras.h" |
| 23 | #include <iostream> |
| 24 | #include <sstream> |
| 25 | |
| 26 | using namespace llvm; |
| 27 | |
Reid Spencer | 926572c | 2004-06-09 06:14:52 +0000 | [diff] [blame] | 28 | // Enable to trace to figure out what the heck is going on when parsing fails |
| 29 | //#define TRACE_LEVEL 10 |
| 30 | //#define DEBUG_OUTPUT |
| 31 | |
| 32 | #if TRACE_LEVEL // ByteCodeReading_TRACEr |
| 33 | #define BCR_TRACE(n, X) \ |
| 34 | if (n < TRACE_LEVEL) std::cerr << std::string(n*2, ' ') << X |
| 35 | #else |
| 36 | #define BCR_TRACE(n, X) |
| 37 | #endif |
| 38 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 39 | #define PARSE_ERROR(inserters) { \ |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 40 | std::ostringstream errormsg; \ |
| 41 | errormsg << inserters; \ |
| 42 | if ( ! handler->handleError( errormsg.str() ) ) \ |
| 43 | throw std::string(errormsg.str()); \ |
| 44 | } |
| 45 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 46 | inline bool AbstractBytecodeParser::moreInBlock() { |
| 47 | return At < BlockEnd; |
| 48 | } |
Reid Spencer | 926572c | 2004-06-09 06:14:52 +0000 | [diff] [blame] | 49 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 50 | inline void AbstractBytecodeParser::checkPastBlockEnd(const char * block_name) { |
| 51 | if ( At > BlockEnd ) |
| 52 | PARSE_ERROR("Attempt to read past the end of " << block_name << " block."); |
| 53 | } |
| 54 | |
| 55 | inline void AbstractBytecodeParser::align32() { |
| 56 | BufPtr Save = At; |
| 57 | At = (const unsigned char *)((unsigned long)(At+3) & (~3UL)); |
| 58 | if ( reportAlignment && At > Save ) handler->handleAlignment( At - Save ); |
| 59 | if (At > BlockEnd) |
| 60 | throw std::string("Ran out of data while aligning!"); |
| 61 | } |
| 62 | |
| 63 | inline unsigned AbstractBytecodeParser::read_uint() { |
| 64 | if (At+4 > BlockEnd) |
| 65 | throw std::string("Ran out of data reading uint!"); |
| 66 | At += 4; |
| 67 | return At[-4] | (At[-3] << 8) | (At[-2] << 16) | (At[-1] << 24); |
| 68 | } |
| 69 | |
| 70 | inline unsigned AbstractBytecodeParser::read_vbr_uint() { |
| 71 | unsigned Shift = 0; |
| 72 | unsigned Result = 0; |
| 73 | BufPtr Save = At; |
| 74 | |
| 75 | do { |
| 76 | if (At == BlockEnd) |
| 77 | throw std::string("Ran out of data reading vbr_uint!"); |
| 78 | Result |= (unsigned)((*At++) & 0x7F) << Shift; |
| 79 | Shift += 7; |
| 80 | } while (At[-1] & 0x80); |
| 81 | if (reportVBR) |
| 82 | handler->handleVBR32(At-Save); |
| 83 | return Result; |
| 84 | } |
| 85 | |
| 86 | inline uint64_t AbstractBytecodeParser::read_vbr_uint64() { |
| 87 | unsigned Shift = 0; |
| 88 | uint64_t Result = 0; |
| 89 | BufPtr Save = At; |
| 90 | |
| 91 | do { |
| 92 | if (At == BlockEnd) |
| 93 | throw std::string("Ran out of data reading vbr_uint64!"); |
| 94 | Result |= (uint64_t)((*At++) & 0x7F) << Shift; |
| 95 | Shift += 7; |
| 96 | } while (At[-1] & 0x80); |
| 97 | if (reportVBR) |
| 98 | handler->handleVBR64(At-Save); |
| 99 | return Result; |
| 100 | } |
| 101 | |
| 102 | inline int64_t AbstractBytecodeParser::read_vbr_int64() { |
| 103 | uint64_t R = read_vbr_uint64(); |
| 104 | if (R & 1) { |
| 105 | if (R != 1) |
| 106 | return -(int64_t)(R >> 1); |
| 107 | else // There is no such thing as -0 with integers. "-0" really means |
| 108 | // 0x8000000000000000. |
| 109 | return 1LL << 63; |
| 110 | } else |
| 111 | return (int64_t)(R >> 1); |
| 112 | } |
| 113 | |
| 114 | inline std::string AbstractBytecodeParser::read_str() { |
| 115 | unsigned Size = read_vbr_uint(); |
| 116 | const unsigned char *OldAt = At; |
| 117 | At += Size; |
| 118 | if (At > BlockEnd) // Size invalid? |
| 119 | throw std::string("Ran out of data reading a string!"); |
| 120 | return std::string((char*)OldAt, Size); |
| 121 | } |
| 122 | |
| 123 | inline void AbstractBytecodeParser::read_data(void *Ptr, void *End) { |
| 124 | unsigned char *Start = (unsigned char *)Ptr; |
| 125 | unsigned Amount = (unsigned char *)End - Start; |
| 126 | if (At+Amount > BlockEnd) |
| 127 | throw std::string("Ran out of data!"); |
| 128 | std::copy(At, At+Amount, Start); |
| 129 | At += Amount; |
| 130 | } |
| 131 | |
| 132 | inline void AbstractBytecodeParser::readBlock(unsigned &Type, unsigned &Size) { |
| 133 | Type = read_uint(); |
| 134 | Size = read_uint(); |
| 135 | BlockStart = At; |
| 136 | if ( At + Size > BlockEnd ) |
| 137 | throw std::string("Attempt to size a block past end of memory"); |
| 138 | BlockEnd = At + Size; |
| 139 | if ( reportBlocks ) { |
| 140 | handler->handleBlock( Type, BlockStart, Size ); |
| 141 | } |
Reid Spencer | 926572c | 2004-06-09 06:14:52 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 144 | const Type *AbstractBytecodeParser::getType(unsigned ID) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 145 | //cerr << "Looking up Type ID: " << ID << "\n"; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 146 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 147 | if (ID < Type::FirstDerivedTyID) |
| 148 | if (const Type *T = Type::getPrimitiveType((Type::PrimitiveID)ID)) |
| 149 | return T; // Asked for a primitive type... |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 150 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 151 | // Otherwise, derived types need offset... |
| 152 | ID -= Type::FirstDerivedTyID; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 153 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 154 | if (!CompactionTypeTable.empty()) { |
| 155 | if (ID >= CompactionTypeTable.size()) |
| 156 | PARSE_ERROR("Type ID out of range for compaction table!"); |
| 157 | return CompactionTypeTable[ID]; |
| 158 | } |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 159 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 160 | // Is it a module-level type? |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 161 | if (ID < ModuleTypes.size()) |
| 162 | return ModuleTypes[ID].get(); |
| 163 | |
| 164 | // Nope, is it a function-level type? |
| 165 | ID -= ModuleTypes.size(); |
| 166 | if (ID < FunctionTypes.size()) |
| 167 | return FunctionTypes[ID].get(); |
| 168 | |
| 169 | PARSE_ERROR("Illegal type reference!"); |
| 170 | return Type::VoidTy; |
| 171 | } |
| 172 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 173 | bool AbstractBytecodeParser::ParseInstruction(std::vector<unsigned> &Operands) { |
| 174 | BufPtr SaveAt = At; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 175 | Operands.clear(); |
| 176 | unsigned iType = 0; |
| 177 | unsigned Opcode = 0; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 178 | unsigned Op = read_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 179 | |
| 180 | // bits Instruction format: Common to all formats |
| 181 | // -------------------------- |
| 182 | // 01-00: Opcode type, fixed to 1. |
| 183 | // 07-02: Opcode |
| 184 | Opcode = (Op >> 2) & 63; |
| 185 | Operands.resize((Op >> 0) & 03); |
| 186 | |
| 187 | switch (Operands.size()) { |
| 188 | case 1: |
| 189 | // bits Instruction format: |
| 190 | // -------------------------- |
| 191 | // 19-08: Resulting type plane |
| 192 | // 31-20: Operand #1 (if set to (2^12-1), then zero operands) |
| 193 | // |
| 194 | iType = (Op >> 8) & 4095; |
| 195 | Operands[0] = (Op >> 20) & 4095; |
| 196 | if (Operands[0] == 4095) // Handle special encoding for 0 operands... |
| 197 | Operands.resize(0); |
| 198 | break; |
| 199 | case 2: |
| 200 | // bits Instruction format: |
| 201 | // -------------------------- |
| 202 | // 15-08: Resulting type plane |
| 203 | // 23-16: Operand #1 |
| 204 | // 31-24: Operand #2 |
| 205 | // |
| 206 | iType = (Op >> 8) & 255; |
| 207 | Operands[0] = (Op >> 16) & 255; |
| 208 | Operands[1] = (Op >> 24) & 255; |
| 209 | break; |
| 210 | case 3: |
| 211 | // bits Instruction format: |
| 212 | // -------------------------- |
| 213 | // 13-08: Resulting type plane |
| 214 | // 19-14: Operand #1 |
| 215 | // 25-20: Operand #2 |
| 216 | // 31-26: Operand #3 |
| 217 | // |
| 218 | iType = (Op >> 8) & 63; |
| 219 | Operands[0] = (Op >> 14) & 63; |
| 220 | Operands[1] = (Op >> 20) & 63; |
| 221 | Operands[2] = (Op >> 26) & 63; |
| 222 | break; |
| 223 | case 0: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 224 | At -= 4; // Hrm, try this again... |
| 225 | Opcode = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 226 | Opcode >>= 2; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 227 | iType = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 228 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 229 | unsigned NumOperands = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 230 | Operands.resize(NumOperands); |
| 231 | |
| 232 | if (NumOperands == 0) |
| 233 | PARSE_ERROR("Zero-argument instruction found; this is invalid."); |
| 234 | |
| 235 | for (unsigned i = 0; i != NumOperands; ++i) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 236 | Operands[i] = read_vbr_uint(); |
| 237 | align32(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 238 | break; |
| 239 | } |
| 240 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 241 | return handler->handleInstruction(Opcode, getType(iType), Operands, At-SaveAt); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 242 | } |
| 243 | |
| 244 | /// ParseBasicBlock - In LLVM 1.0 bytecode files, we used to output one |
| 245 | /// basicblock at a time. This method reads in one of the basicblock packets. |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 246 | void AbstractBytecodeParser::ParseBasicBlock( unsigned BlockNo) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 247 | handler->handleBasicBlockBegin( BlockNo ); |
| 248 | |
| 249 | std::vector<unsigned> Args; |
| 250 | bool is_terminating = false; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 251 | while ( moreInBlock() ) |
| 252 | is_terminating = ParseInstruction(Args); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 253 | |
| 254 | if ( ! is_terminating ) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 255 | PARSE_ERROR("Non-terminated basic block found!"); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 256 | |
| 257 | handler->handleBasicBlockEnd( BlockNo ); |
| 258 | } |
| 259 | |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 260 | /// ParseInstructionList - Parse all of the BasicBlock's & Instruction's in the |
| 261 | /// body of a function. In post 1.0 bytecode files, we no longer emit basic |
| 262 | /// block individually, in order to avoid per-basic-block overhead. |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 263 | unsigned AbstractBytecodeParser::ParseInstructionList() { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 264 | unsigned BlockNo = 0; |
| 265 | std::vector<unsigned> Args; |
| 266 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 267 | while ( moreInBlock() ) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 268 | handler->handleBasicBlockBegin( BlockNo ); |
| 269 | |
| 270 | // Read instructions into this basic block until we get to a terminator |
| 271 | bool is_terminating = false; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 272 | while (moreInBlock() && !is_terminating ) |
| 273 | is_terminating = ParseInstruction(Args ) ; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 274 | |
| 275 | if (!is_terminating) |
| 276 | PARSE_ERROR( "Non-terminated basic block found!"); |
| 277 | |
| 278 | handler->handleBasicBlockEnd( BlockNo ); |
| 279 | ++BlockNo; |
| 280 | } |
| 281 | return BlockNo; |
| 282 | } |
| 283 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 284 | void AbstractBytecodeParser::ParseSymbolTable() { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 285 | handler->handleSymbolTableBegin(); |
| 286 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 287 | while ( moreInBlock() ) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 288 | // Symtab block header: [num entries][type id number] |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 289 | unsigned NumEntries = read_vbr_uint(); |
| 290 | unsigned Typ = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 291 | const Type *Ty = getType(Typ); |
| 292 | |
| 293 | handler->handleSymbolTablePlane( Typ, NumEntries, Ty ); |
| 294 | |
| 295 | for (unsigned i = 0; i != NumEntries; ++i) { |
| 296 | // Symtab entry: [def slot #][name] |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 297 | unsigned slot = read_vbr_uint(); |
| 298 | std::string Name = read_str(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 299 | |
| 300 | if (Typ == Type::TypeTyID) |
| 301 | handler->handleSymbolTableType( i, slot, Name ); |
| 302 | else |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 303 | handler->handleSymbolTableValue( i, slot, Name ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 304 | } |
| 305 | } |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 306 | checkPastBlockEnd("Symbol Table"); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 307 | |
| 308 | handler->handleSymbolTableEnd(); |
| 309 | } |
| 310 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 311 | void AbstractBytecodeParser::ParseFunctionLazily() { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 312 | if (FunctionSignatureList.empty()) |
| 313 | throw std::string("FunctionSignatureList empty!"); |
| 314 | |
| 315 | const Type *FType = FunctionSignatureList.back(); |
| 316 | FunctionSignatureList.pop_back(); |
| 317 | |
| 318 | // Save the information for future reading of the function |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 319 | LazyFunctionLoadMap[FType] = LazyFunctionInfo(BlockStart, BlockEnd); |
| 320 | |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 321 | // Pretend we've `parsed' this function |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 322 | At = BlockEnd; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | void AbstractBytecodeParser::ParseNextFunction(Type* FType) { |
| 326 | // Find {start, end} pointers and slot in the map. If not there, we're done. |
| 327 | LazyFunctionMap::iterator Fi = LazyFunctionLoadMap.find(FType); |
| 328 | |
| 329 | // Make sure we found it |
| 330 | if ( Fi == LazyFunctionLoadMap.end() ) { |
| 331 | PARSE_ERROR("Unrecognized function of type " << FType->getDescription()); |
| 332 | return; |
| 333 | } |
| 334 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 335 | BlockStart = At = Fi->second.Buf; |
| 336 | BlockEnd = Fi->second.Buf; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 337 | assert(Fi->first == FType); |
| 338 | |
| 339 | LazyFunctionLoadMap.erase(Fi); |
| 340 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 341 | this->ParseFunctionBody( FType ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 342 | } |
| 343 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 344 | void AbstractBytecodeParser::ParseFunctionBody(const Type* FType ) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 345 | |
| 346 | GlobalValue::LinkageTypes Linkage = GlobalValue::ExternalLinkage; |
| 347 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 348 | unsigned LinkageType = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 349 | switch (LinkageType) { |
| 350 | case 0: Linkage = GlobalValue::ExternalLinkage; break; |
| 351 | case 1: Linkage = GlobalValue::WeakLinkage; break; |
| 352 | case 2: Linkage = GlobalValue::AppendingLinkage; break; |
| 353 | case 3: Linkage = GlobalValue::InternalLinkage; break; |
| 354 | case 4: Linkage = GlobalValue::LinkOnceLinkage; break; |
| 355 | default: |
| 356 | PARSE_ERROR("Invalid linkage type for Function."); |
| 357 | Linkage = GlobalValue::InternalLinkage; |
| 358 | break; |
| 359 | } |
| 360 | |
| 361 | handler->handleFunctionBegin(FType,Linkage); |
| 362 | |
| 363 | // Keep track of how many basic blocks we have read in... |
| 364 | unsigned BlockNum = 0; |
| 365 | bool InsertedArguments = false; |
| 366 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 367 | BufPtr MyEnd = BlockEnd; |
| 368 | while ( At < MyEnd ) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 369 | unsigned Type, Size; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 370 | BufPtr OldAt = At; |
| 371 | readBlock(Type, Size); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 372 | |
| 373 | switch (Type) { |
| 374 | case BytecodeFormat::ConstantPool: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 375 | ParseConstantPool(FunctionTypes ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 376 | break; |
| 377 | |
| 378 | case BytecodeFormat::CompactionTable: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 379 | ParseCompactionTable(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 380 | break; |
| 381 | |
| 382 | case BytecodeFormat::BasicBlock: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 383 | ParseBasicBlock(BlockNum++); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 384 | break; |
| 385 | |
| 386 | case BytecodeFormat::InstructionList: |
| 387 | if (BlockNum) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 388 | PARSE_ERROR("InstructionList must come before basic blocks!"); |
| 389 | BlockNum = ParseInstructionList(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 390 | break; |
| 391 | |
| 392 | case BytecodeFormat::SymbolTable: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 393 | ParseSymbolTable(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 394 | break; |
| 395 | |
| 396 | default: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 397 | At += Size; |
| 398 | if (OldAt > At) |
| 399 | PARSE_ERROR("Wrapped around reading bytecode"); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 400 | break; |
| 401 | } |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 402 | BlockEnd = MyEnd; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 403 | |
| 404 | // Malformed bc file if read past end of block. |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 405 | align32(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 406 | } |
| 407 | |
| 408 | handler->handleFunctionEnd(FType); |
| 409 | |
| 410 | // Clear out function-level types... |
| 411 | FunctionTypes.clear(); |
| 412 | CompactionTypeTable.clear(); |
| 413 | } |
| 414 | |
| 415 | void AbstractBytecodeParser::ParseAllFunctionBodies() { |
| 416 | LazyFunctionMap::iterator Fi = LazyFunctionLoadMap.begin(); |
| 417 | LazyFunctionMap::iterator Fe = LazyFunctionLoadMap.end(); |
| 418 | |
| 419 | while ( Fi != Fe ) { |
| 420 | const Type* FType = Fi->first; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 421 | BlockStart = At = Fi->second.Buf; |
| 422 | BlockEnd = Fi->second.EndBuf; |
| 423 | this->ParseFunctionBody(FType); |
| 424 | ++Fi; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 425 | } |
| 426 | } |
| 427 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 428 | void AbstractBytecodeParser::ParseCompactionTable() { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 429 | |
| 430 | handler->handleCompactionTableBegin(); |
| 431 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 432 | while ( moreInBlock() ) { |
| 433 | unsigned NumEntries = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 434 | unsigned Ty; |
| 435 | |
| 436 | if ((NumEntries & 3) == 3) { |
| 437 | NumEntries >>= 2; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 438 | Ty = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 439 | } else { |
| 440 | Ty = NumEntries >> 2; |
| 441 | NumEntries &= 3; |
| 442 | } |
| 443 | |
| 444 | handler->handleCompactionTablePlane( Ty, NumEntries ); |
| 445 | |
| 446 | if (Ty == Type::TypeTyID) { |
| 447 | for (unsigned i = 0; i != NumEntries; ++i) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 448 | unsigned TypeSlot = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 449 | const Type *Typ = getGlobalTableType(TypeSlot); |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 450 | handler->handleCompactionTableType( i, TypeSlot, Typ ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 451 | } |
| 452 | } else { |
| 453 | const Type *Typ = getType(Ty); |
| 454 | // Push the implicit zero |
| 455 | for (unsigned i = 0; i != NumEntries; ++i) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 456 | unsigned ValSlot = read_vbr_uint(); |
| 457 | handler->handleCompactionTableValue( i, ValSlot, Typ ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 458 | } |
| 459 | } |
| 460 | } |
| 461 | handler->handleCompactionTableEnd(); |
| 462 | } |
| 463 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 464 | const Type *AbstractBytecodeParser::ParseTypeConstant() { |
| 465 | unsigned PrimType = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 466 | |
| 467 | const Type *Val = 0; |
| 468 | if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType))) |
| 469 | return Val; |
| 470 | |
| 471 | switch (PrimType) { |
| 472 | case Type::FunctionTyID: { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 473 | const Type *RetType = getType(read_vbr_uint()); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 474 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 475 | unsigned NumParams = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 476 | |
| 477 | std::vector<const Type*> Params; |
| 478 | while (NumParams--) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 479 | Params.push_back(getType(read_vbr_uint())); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 480 | |
| 481 | bool isVarArg = Params.size() && Params.back() == Type::VoidTy; |
| 482 | if (isVarArg) Params.pop_back(); |
| 483 | |
| 484 | Type* result = FunctionType::get(RetType, Params, isVarArg); |
| 485 | handler->handleType( result ); |
| 486 | return result; |
| 487 | } |
| 488 | case Type::ArrayTyID: { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 489 | unsigned ElTyp = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 490 | const Type *ElementType = getType(ElTyp); |
| 491 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 492 | unsigned NumElements = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 493 | |
| 494 | BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size=" |
| 495 | << NumElements << "\n"); |
| 496 | Type* result = ArrayType::get(ElementType, NumElements); |
| 497 | handler->handleType( result ); |
| 498 | return result; |
| 499 | } |
| 500 | case Type::StructTyID: { |
| 501 | std::vector<const Type*> Elements; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 502 | unsigned Typ = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 503 | while (Typ) { // List is terminated by void/0 typeid |
| 504 | Elements.push_back(getType(Typ)); |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 505 | Typ = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 506 | } |
| 507 | |
| 508 | Type* result = StructType::get(Elements); |
| 509 | handler->handleType( result ); |
| 510 | return result; |
| 511 | } |
| 512 | case Type::PointerTyID: { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 513 | unsigned ElTyp = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 514 | BCR_TRACE(5, "Pointer Type Constant #" << ElTyp << "\n"); |
| 515 | Type* result = PointerType::get(getType(ElTyp)); |
| 516 | handler->handleType( result ); |
| 517 | return result; |
| 518 | } |
| 519 | |
| 520 | case Type::OpaqueTyID: { |
| 521 | Type* result = OpaqueType::get(); |
| 522 | handler->handleType( result ); |
| 523 | return result; |
| 524 | } |
| 525 | |
| 526 | default: |
| 527 | PARSE_ERROR("Don't know how to deserialize primitive type" << PrimType << "\n"); |
| 528 | return Val; |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | // ParseTypeConstants - We have to use this weird code to handle recursive |
| 533 | // types. We know that recursive types will only reference the current slab of |
| 534 | // values in the type plane, but they can forward reference types before they |
| 535 | // have been read. For example, Type #0 might be '{ Ty#1 }' and Type #1 might |
| 536 | // be 'Ty#0*'. When reading Type #0, type number one doesn't exist. To fix |
| 537 | // this ugly problem, we pessimistically insert an opaque type for each type we |
| 538 | // are about to read. This means that forward references will resolve to |
| 539 | // something and when we reread the type later, we can replace the opaque type |
| 540 | // with a new resolved concrete type. |
| 541 | // |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 542 | void AbstractBytecodeParser::ParseTypeConstants( |
| 543 | TypeListTy &Tab, unsigned NumEntries |
| 544 | ) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 545 | assert(Tab.size() == 0 && "should not have read type constants in before!"); |
| 546 | |
| 547 | // Insert a bunch of opaque types to be resolved later... |
| 548 | Tab.reserve(NumEntries); |
| 549 | for (unsigned i = 0; i != NumEntries; ++i) |
| 550 | Tab.push_back(OpaqueType::get()); |
| 551 | |
| 552 | // Loop through reading all of the types. Forward types will make use of the |
| 553 | // opaque types just inserted. |
| 554 | // |
| 555 | for (unsigned i = 0; i != NumEntries; ++i) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 556 | const Type *NewTy = ParseTypeConstant(), *OldTy = Tab[i].get(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 557 | if (NewTy == 0) throw std::string("Couldn't parse type!"); |
| 558 | BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy << |
| 559 | "' Replacing: " << OldTy << "\n"); |
| 560 | |
| 561 | // Don't insertValue the new type... instead we want to replace the opaque |
| 562 | // type with the new concrete value... |
| 563 | // |
| 564 | |
| 565 | // Refine the abstract type to the new type. This causes all uses of the |
| 566 | // abstract type to use NewTy. This also will cause the opaque type to be |
| 567 | // deleted... |
| 568 | // |
| 569 | cast<DerivedType>(const_cast<Type*>(OldTy))->refineAbstractTypeTo(NewTy); |
| 570 | |
| 571 | // This should have replace the old opaque type with the new type in the |
| 572 | // value table... or with a preexisting type that was already in the system |
| 573 | assert(Tab[i] != OldTy && "refineAbstractType didn't work!"); |
| 574 | } |
| 575 | |
| 576 | BCR_TRACE(5, "Resulting types:\n"); |
| 577 | for (unsigned i = 0; i < NumEntries; ++i) { |
| 578 | BCR_TRACE(5, (void*)Tab[i].get() << " - " << Tab[i].get() << "\n"); |
| 579 | } |
| 580 | } |
| 581 | |
| 582 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 583 | void AbstractBytecodeParser::ParseConstantValue(unsigned TypeID) { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 584 | |
| 585 | // We must check for a ConstantExpr before switching by type because |
| 586 | // a ConstantExpr can be of any type, and has no explicit value. |
| 587 | // |
| 588 | // 0 if not expr; numArgs if is expr |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 589 | unsigned isExprNumArgs = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 590 | |
| 591 | if (isExprNumArgs) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 592 | unsigned Opcode = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 593 | const Type* Typ = getType(TypeID); |
| 594 | |
| 595 | // FIXME: Encoding of constant exprs could be much more compact! |
| 596 | std::vector<std::pair<const Type*,unsigned> > ArgVec; |
| 597 | ArgVec.reserve(isExprNumArgs); |
| 598 | |
| 599 | // Read the slot number and types of each of the arguments |
| 600 | for (unsigned i = 0; i != isExprNumArgs; ++i) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 601 | unsigned ArgValSlot = read_vbr_uint(); |
| 602 | unsigned ArgTypeSlot = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 603 | BCR_TRACE(4, "CE Arg " << i << ": Type: '" << *getType(ArgTypeSlot) |
| 604 | << "' slot: " << ArgValSlot << "\n"); |
| 605 | |
| 606 | // Get the arg value from its slot if it exists, otherwise a placeholder |
| 607 | ArgVec.push_back(std::make_pair(getType(ArgTypeSlot), ArgValSlot)); |
| 608 | } |
| 609 | |
| 610 | handler->handleConstantExpression( Opcode, Typ, ArgVec ); |
| 611 | return; |
| 612 | } |
| 613 | |
| 614 | // Ok, not an ConstantExpr. We now know how to read the given type... |
| 615 | const Type *Ty = getType(TypeID); |
| 616 | switch (Ty->getPrimitiveID()) { |
| 617 | case Type::BoolTyID: { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 618 | unsigned Val = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 619 | if (Val != 0 && Val != 1) |
| 620 | PARSE_ERROR("Invalid boolean value read."); |
| 621 | |
| 622 | handler->handleConstantValue( ConstantBool::get(Val == 1)); |
| 623 | break; |
| 624 | } |
| 625 | |
| 626 | case Type::UByteTyID: // Unsigned integer types... |
| 627 | case Type::UShortTyID: |
| 628 | case Type::UIntTyID: { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 629 | unsigned Val = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 630 | if (!ConstantUInt::isValueValidForType(Ty, Val)) |
| 631 | throw std::string("Invalid unsigned byte/short/int read."); |
| 632 | handler->handleConstantValue( ConstantUInt::get(Ty, Val) ); |
| 633 | break; |
| 634 | } |
| 635 | |
| 636 | case Type::ULongTyID: { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 637 | handler->handleConstantValue( ConstantUInt::get(Ty, read_vbr_uint64()) ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 638 | break; |
| 639 | } |
| 640 | |
| 641 | case Type::SByteTyID: // Signed integer types... |
| 642 | case Type::ShortTyID: |
| 643 | case Type::IntTyID: { |
| 644 | case Type::LongTyID: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 645 | int64_t Val = read_vbr_int64(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 646 | if (!ConstantSInt::isValueValidForType(Ty, Val)) |
| 647 | throw std::string("Invalid signed byte/short/int/long read."); |
| 648 | handler->handleConstantValue( ConstantSInt::get(Ty, Val) ); |
| 649 | break; |
| 650 | } |
| 651 | |
| 652 | case Type::FloatTyID: { |
| 653 | float F; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 654 | read_data(&F, &F+1); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 655 | handler->handleConstantValue( ConstantFP::get(Ty, F) ); |
| 656 | break; |
| 657 | } |
| 658 | |
| 659 | case Type::DoubleTyID: { |
| 660 | double Val; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 661 | read_data(&Val, &Val+1); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 662 | handler->handleConstantValue( ConstantFP::get(Ty, Val) ); |
| 663 | break; |
| 664 | } |
| 665 | |
| 666 | case Type::TypeTyID: |
| 667 | PARSE_ERROR("Type constants shouldn't live in constant table!"); |
| 668 | break; |
| 669 | |
| 670 | case Type::ArrayTyID: { |
| 671 | const ArrayType *AT = cast<ArrayType>(Ty); |
| 672 | unsigned NumElements = AT->getNumElements(); |
| 673 | std::vector<unsigned> Elements; |
| 674 | Elements.reserve(NumElements); |
| 675 | while (NumElements--) // Read all of the elements of the constant. |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 676 | Elements.push_back(read_vbr_uint()); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 677 | |
| 678 | handler->handleConstantArray( AT, Elements ); |
| 679 | break; |
| 680 | } |
| 681 | |
| 682 | case Type::StructTyID: { |
| 683 | const StructType *ST = cast<StructType>(Ty); |
| 684 | std::vector<unsigned> Elements; |
| 685 | Elements.reserve(ST->getNumElements()); |
| 686 | for (unsigned i = 0; i != ST->getNumElements(); ++i) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 687 | Elements.push_back(read_vbr_uint()); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 688 | handler->handleConstantStruct( ST, Elements ); |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 689 | break; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 690 | } |
| 691 | |
| 692 | case Type::PointerTyID: { // ConstantPointerRef value... |
| 693 | const PointerType *PT = cast<PointerType>(Ty); |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 694 | unsigned Slot = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 695 | handler->handleConstantPointer( PT, Slot ); |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 696 | break; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 697 | } |
| 698 | |
| 699 | default: |
| 700 | PARSE_ERROR("Don't know how to deserialize constant value of type '"+ |
| 701 | Ty->getDescription()); |
| 702 | } |
| 703 | } |
| 704 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 705 | void AbstractBytecodeParser::ParseGlobalTypes() { |
| 706 | ParseConstantPool(ModuleTypes); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 707 | } |
| 708 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 709 | void AbstractBytecodeParser::ParseStringConstants(unsigned NumEntries ){ |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 710 | for (; NumEntries; --NumEntries) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 711 | unsigned Typ = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 712 | const Type *Ty = getType(Typ); |
| 713 | if (!isa<ArrayType>(Ty)) |
| 714 | throw std::string("String constant data invalid!"); |
| 715 | |
| 716 | const ArrayType *ATy = cast<ArrayType>(Ty); |
| 717 | if (ATy->getElementType() != Type::SByteTy && |
| 718 | ATy->getElementType() != Type::UByteTy) |
| 719 | throw std::string("String constant data invalid!"); |
| 720 | |
| 721 | // Read character data. The type tells us how long the string is. |
| 722 | char Data[ATy->getNumElements()]; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 723 | read_data(Data, Data+ATy->getNumElements()); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 724 | |
| 725 | std::vector<Constant*> Elements(ATy->getNumElements()); |
| 726 | if (ATy->getElementType() == Type::SByteTy) |
| 727 | for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) |
| 728 | Elements[i] = ConstantSInt::get(Type::SByteTy, (signed char)Data[i]); |
| 729 | else |
| 730 | for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) |
| 731 | Elements[i] = ConstantUInt::get(Type::UByteTy, (unsigned char)Data[i]); |
| 732 | |
| 733 | // Create the constant, inserting it as needed. |
| 734 | ConstantArray *C = cast<ConstantArray>( ConstantArray::get(ATy, Elements) ); |
| 735 | handler->handleConstantString( C ); |
| 736 | } |
| 737 | } |
| 738 | |
| 739 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 740 | void AbstractBytecodeParser::ParseConstantPool( TypeListTy &TypeTab) { |
| 741 | while ( moreInBlock() ) { |
| 742 | unsigned NumEntries = read_vbr_uint(); |
| 743 | unsigned Typ = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 744 | if (Typ == Type::TypeTyID) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 745 | ParseTypeConstants(TypeTab, NumEntries); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 746 | } else if (Typ == Type::VoidTyID) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 747 | ParseStringConstants(NumEntries); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 748 | } else { |
| 749 | BCR_TRACE(3, "Type: '" << *getType(Typ) << "' NumEntries: " |
| 750 | << NumEntries << "\n"); |
| 751 | |
| 752 | for (unsigned i = 0; i < NumEntries; ++i) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 753 | ParseConstantValue(Typ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 754 | } |
| 755 | } |
| 756 | } |
| 757 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 758 | checkPastBlockEnd("Constant Pool"); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 759 | } |
| 760 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 761 | void AbstractBytecodeParser::ParseModuleGlobalInfo() { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 762 | |
| 763 | handler->handleModuleGlobalsBegin(); |
| 764 | |
| 765 | // Read global variables... |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 766 | unsigned VarType = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 767 | while (VarType != Type::VoidTyID) { // List is terminated by Void |
| 768 | // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3,4 = |
| 769 | // Linkage, bit4+ = slot# |
| 770 | unsigned SlotNo = VarType >> 5; |
| 771 | unsigned LinkageID = (VarType >> 2) & 7; |
| 772 | bool isConstant = VarType & 1; |
| 773 | bool hasInitializer = VarType & 2; |
| 774 | GlobalValue::LinkageTypes Linkage; |
| 775 | |
| 776 | switch (LinkageID) { |
| 777 | case 0: Linkage = GlobalValue::ExternalLinkage; break; |
| 778 | case 1: Linkage = GlobalValue::WeakLinkage; break; |
| 779 | case 2: Linkage = GlobalValue::AppendingLinkage; break; |
| 780 | case 3: Linkage = GlobalValue::InternalLinkage; break; |
| 781 | case 4: Linkage = GlobalValue::LinkOnceLinkage; break; |
| 782 | default: |
| 783 | PARSE_ERROR("Unknown linkage type: " << LinkageID); |
| 784 | Linkage = GlobalValue::InternalLinkage; |
| 785 | break; |
| 786 | } |
| 787 | |
| 788 | const Type *Ty = getType(SlotNo); |
| 789 | if ( !Ty ) { |
| 790 | PARSE_ERROR("Global has no type! SlotNo=" << SlotNo); |
| 791 | } |
| 792 | |
| 793 | if ( !isa<PointerType>(Ty)) { |
| 794 | PARSE_ERROR("Global not a pointer type! Ty= " << Ty->getDescription()); |
| 795 | } |
| 796 | |
| 797 | const Type *ElTy = cast<PointerType>(Ty)->getElementType(); |
| 798 | |
| 799 | // Create the global variable... |
Reid Spencer | 5e8868d | 2004-06-08 05:54:47 +0000 | [diff] [blame] | 800 | if (hasInitializer) { |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 801 | unsigned initSlot = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 802 | handler->handleInitializedGV( ElTy, isConstant, Linkage, initSlot ); |
Reid Spencer | 5e8868d | 2004-06-08 05:54:47 +0000 | [diff] [blame] | 803 | } else |
| 804 | handler->handleGlobalVariable( ElTy, isConstant, Linkage ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 805 | |
| 806 | // Get next item |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 807 | VarType = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 808 | } |
| 809 | |
| 810 | // Read the function objects for all of the functions that are coming |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 811 | unsigned FnSignature = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 812 | while (FnSignature != Type::VoidTyID) { // List is terminated by Void |
| 813 | const Type *Ty = getType(FnSignature); |
| 814 | if (!isa<PointerType>(Ty) || |
| 815 | !isa<FunctionType>(cast<PointerType>(Ty)->getElementType())) { |
| 816 | PARSE_ERROR( "Function not a pointer to function type! Ty = " + |
| 817 | Ty->getDescription()); |
| 818 | // FIXME: what should Ty be if handler continues? |
| 819 | } |
| 820 | |
| 821 | // We create functions by passing the underlying FunctionType to create... |
| 822 | Ty = cast<PointerType>(Ty)->getElementType(); |
| 823 | |
| 824 | // Save this for later so we know type of lazily instantiated functions |
| 825 | FunctionSignatureList.push_back(Ty); |
| 826 | |
| 827 | handler->handleFunctionDeclaration(Ty); |
| 828 | |
| 829 | // Get Next function signature |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 830 | FnSignature = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 831 | } |
| 832 | |
| 833 | if (hasInconsistentModuleGlobalInfo) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 834 | align32(); |
| 835 | |
| 836 | // Now that the function signature list is set up, reverse it so that we can |
| 837 | // remove elements efficiently from the back of the vector. |
| 838 | std::reverse(FunctionSignatureList.begin(), FunctionSignatureList.end()); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 839 | |
| 840 | // This is for future proofing... in the future extra fields may be added that |
| 841 | // we don't understand, so we transparently ignore them. |
| 842 | // |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 843 | At = BlockEnd; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 844 | |
| 845 | handler->handleModuleGlobalsEnd(); |
| 846 | } |
| 847 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 848 | void AbstractBytecodeParser::ParseVersionInfo() { |
| 849 | unsigned Version = read_vbr_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 850 | |
| 851 | // Unpack version number: low four bits are for flags, top bits = version |
| 852 | Module::Endianness Endianness; |
| 853 | Module::PointerSize PointerSize; |
| 854 | Endianness = (Version & 1) ? Module::BigEndian : Module::LittleEndian; |
| 855 | PointerSize = (Version & 2) ? Module::Pointer64 : Module::Pointer32; |
| 856 | |
| 857 | bool hasNoEndianness = Version & 4; |
| 858 | bool hasNoPointerSize = Version & 8; |
| 859 | |
| 860 | RevisionNum = Version >> 4; |
| 861 | |
| 862 | // Default values for the current bytecode version |
| 863 | hasInconsistentModuleGlobalInfo = false; |
| 864 | hasExplicitPrimitiveZeros = false; |
| 865 | hasRestrictedGEPTypes = false; |
| 866 | |
| 867 | switch (RevisionNum) { |
| 868 | case 0: // LLVM 1.0, 1.1 release version |
| 869 | // Base LLVM 1.0 bytecode format. |
| 870 | hasInconsistentModuleGlobalInfo = true; |
| 871 | hasExplicitPrimitiveZeros = true; |
| 872 | // FALL THROUGH |
| 873 | case 1: // LLVM 1.2 release version |
| 874 | // LLVM 1.2 added explicit support for emitting strings efficiently. |
| 875 | |
| 876 | // Also, it fixed the problem where the size of the ModuleGlobalInfo block |
| 877 | // included the size for the alignment at the end, where the rest of the |
| 878 | // blocks did not. |
| 879 | |
| 880 | // LLVM 1.2 and before required that GEP indices be ubyte constants for |
| 881 | // structures and longs for sequential types. |
| 882 | hasRestrictedGEPTypes = true; |
| 883 | |
| 884 | // FALL THROUGH |
| 885 | case 2: // LLVM 1.3 release version |
| 886 | break; |
| 887 | |
| 888 | default: |
| 889 | PARSE_ERROR("Unknown bytecode version number: " << RevisionNum); |
| 890 | } |
| 891 | |
| 892 | if (hasNoEndianness) Endianness = Module::AnyEndianness; |
| 893 | if (hasNoPointerSize) PointerSize = Module::AnyPointerSize; |
| 894 | |
| 895 | handler->handleVersionInfo(RevisionNum, Endianness, PointerSize ); |
| 896 | } |
| 897 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 898 | void AbstractBytecodeParser::ParseModule() { |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 899 | unsigned Type, Size; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 900 | |
| 901 | FunctionSignatureList.clear(); // Just in case... |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 902 | |
| 903 | // Read into instance variables... |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 904 | ParseVersionInfo(); |
| 905 | align32(); /// FIXME: Is this redundant? VI is first and 4 bytes! |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 906 | |
| 907 | bool SeenModuleGlobalInfo = false; |
| 908 | bool SeenGlobalTypePlane = false; |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 909 | BufPtr MyEnd = BlockEnd; |
| 910 | while (At < MyEnd) { |
| 911 | BufPtr OldAt = At; |
| 912 | readBlock(Type, Size); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 913 | |
| 914 | switch (Type) { |
| 915 | |
| 916 | case BytecodeFormat::GlobalTypePlane: |
| 917 | if ( SeenGlobalTypePlane ) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 918 | PARSE_ERROR("Two GlobalTypePlane Blocks Encountered!"); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 919 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 920 | ParseGlobalTypes(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 921 | SeenGlobalTypePlane = true; |
| 922 | break; |
| 923 | |
| 924 | case BytecodeFormat::ModuleGlobalInfo: |
| 925 | if ( SeenModuleGlobalInfo ) |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 926 | PARSE_ERROR("Two ModuleGlobalInfo Blocks Encountered!"); |
| 927 | ParseModuleGlobalInfo(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 928 | SeenModuleGlobalInfo = true; |
| 929 | break; |
| 930 | |
| 931 | case BytecodeFormat::ConstantPool: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 932 | ParseConstantPool(ModuleTypes); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 933 | break; |
| 934 | |
| 935 | case BytecodeFormat::Function: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 936 | ParseFunctionLazily(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 937 | break; |
| 938 | |
| 939 | case BytecodeFormat::SymbolTable: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 940 | ParseSymbolTable(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 941 | break; |
| 942 | |
| 943 | default: |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 944 | At += Size; |
| 945 | if (OldAt > At) { |
| 946 | PARSE_ERROR("Unexpected Block of Type" << Type << "encountered!" ); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 947 | } |
| 948 | break; |
| 949 | } |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 950 | BlockEnd = MyEnd; |
| 951 | align32(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 952 | } |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 953 | |
| 954 | /// Make sure we pulled them all out. If we didn't then there's a declaration |
| 955 | /// but a missing body. That's not allowed. |
| 956 | if (!FunctionSignatureList.empty()) |
| 957 | throw std::string( |
| 958 | "Function declared, but bytecode stream ended before definition"); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 959 | } |
| 960 | |
| 961 | void AbstractBytecodeParser::ParseBytecode( |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 962 | BufPtr b, unsigned Length, |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 963 | const std::string &ModuleID) { |
| 964 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 965 | At = MemStart = BlockStart = b; |
| 966 | MemEnd = BlockEnd = b + Length; |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 967 | handler->handleStart(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 968 | |
| 969 | // Read and check signature... |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 970 | unsigned Sig = read_uint(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 971 | if (Sig != ('l' | ('l' << 8) | ('v' << 16) | ('m' << 24))) { |
| 972 | PARSE_ERROR("Invalid bytecode signature: " << Sig); |
| 973 | } |
| 974 | |
| 975 | handler->handleModuleBegin(ModuleID); |
| 976 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 977 | unsigned Type, Size; |
| 978 | readBlock(Type, Size); |
| 979 | if ( Type != BytecodeFormat::Module ) { |
| 980 | PARSE_ERROR("Expected Module Block! At: " << unsigned(intptr_t(At)) |
| 981 | << ", Type:" << Type << ", Size:" << Size); |
| 982 | } |
| 983 | if ( At + Size != MemEnd ) { |
| 984 | PARSE_ERROR("Invalid Top Level Block Length! At: " |
| 985 | << unsigned(intptr_t(At)) << ", Type:" << Type << ", Size:" << Size); |
| 986 | } |
| 987 | this->ParseModule(); |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 988 | |
| 989 | handler->handleModuleEnd(ModuleID); |
| 990 | |
| 991 | handler->handleFinish(); |
| 992 | } |
| 993 | |
Reid Spencer | 00c28a7 | 2004-06-10 08:09:13 +0000 | [diff] [blame^] | 994 | //===----------------------------------------------------------------------===// |
| 995 | //=== Default Implementations of Handler Methods |
| 996 | //===----------------------------------------------------------------------===// |
| 997 | |
| 998 | bool BytecodeHandler::handleError(const std::string& str ) { return false; } |
| 999 | void BytecodeHandler::handleStart() { } |
| 1000 | void BytecodeHandler::handleFinish() { } |
| 1001 | void BytecodeHandler::handleModuleBegin(const std::string& id) { } |
| 1002 | void BytecodeHandler::handleModuleEnd(const std::string& id) { } |
| 1003 | void BytecodeHandler::handleVersionInfo( unsigned char RevisionNum, |
| 1004 | Module::Endianness Endianness, Module::PointerSize PointerSize) { } |
| 1005 | void BytecodeHandler::handleModuleGlobalsBegin() { } |
| 1006 | void BytecodeHandler::handleGlobalVariable( |
| 1007 | const Type* ElemType, bool isConstant, GlobalValue::LinkageTypes ) { } |
| 1008 | void BytecodeHandler::handleInitializedGV( |
| 1009 | const Type* ElemType, bool isConstant, GlobalValue::LinkageTypes, |
| 1010 | unsigned initSlot) {} |
| 1011 | void BytecodeHandler::handleType( const Type* Ty ) {} |
| 1012 | void BytecodeHandler::handleFunctionDeclaration( |
| 1013 | const Type* FuncType) {} |
| 1014 | void BytecodeHandler::handleModuleGlobalsEnd() { } |
| 1015 | void BytecodeHandler::handleCompactionTableBegin() { } |
| 1016 | void BytecodeHandler::handleCompactionTablePlane( unsigned Ty, |
| 1017 | unsigned NumEntries) {} |
| 1018 | void BytecodeHandler::handleCompactionTableType( unsigned i, unsigned TypSlot, |
| 1019 | const Type* ) {} |
| 1020 | void BytecodeHandler::handleCompactionTableValue( unsigned i, unsigned ValSlot, |
| 1021 | const Type* ) {} |
| 1022 | void BytecodeHandler::handleCompactionTableEnd() { } |
| 1023 | void BytecodeHandler::handleSymbolTableBegin() { } |
| 1024 | void BytecodeHandler::handleSymbolTablePlane( unsigned Ty, unsigned NumEntries, |
| 1025 | const Type* Typ) { } |
| 1026 | void BytecodeHandler::handleSymbolTableType( unsigned i, unsigned slot, |
| 1027 | const std::string& name ) { } |
| 1028 | void BytecodeHandler::handleSymbolTableValue( unsigned i, unsigned slot, |
| 1029 | const std::string& name ) { } |
| 1030 | void BytecodeHandler::handleSymbolTableEnd() { } |
| 1031 | void BytecodeHandler::handleFunctionBegin( const Type* FType, |
| 1032 | GlobalValue::LinkageTypes linkage ) { } |
| 1033 | void BytecodeHandler::handleFunctionEnd( const Type* FType) { } |
| 1034 | void BytecodeHandler::handleBasicBlockBegin( unsigned blocknum) { } |
| 1035 | bool BytecodeHandler::handleInstruction( unsigned Opcode, const Type* iType, |
| 1036 | std::vector<unsigned>& Operands, unsigned Size) { |
| 1037 | return Instruction::isTerminator(Opcode); |
| 1038 | } |
| 1039 | void BytecodeHandler::handleBasicBlockEnd(unsigned blocknum) { } |
| 1040 | void BytecodeHandler::handleGlobalConstantsBegin() { } |
| 1041 | void BytecodeHandler::handleConstantExpression( unsigned Opcode, |
| 1042 | const Type* Typ, std::vector<std::pair<const Type*,unsigned> > ArgVec ) { } |
| 1043 | void BytecodeHandler::handleConstantValue( Constant * c ) { } |
| 1044 | void BytecodeHandler::handleConstantArray( const ArrayType* AT, |
| 1045 | std::vector<unsigned>& Elements ) { } |
| 1046 | void BytecodeHandler::handleConstantStruct( const StructType* ST, |
| 1047 | std::vector<unsigned>& ElementSlots) { } |
| 1048 | void BytecodeHandler::handleConstantPointer( |
| 1049 | const PointerType* PT, unsigned Slot) { } |
| 1050 | void BytecodeHandler::handleConstantString( const ConstantArray* CA ) {} |
| 1051 | void BytecodeHandler::handleGlobalConstantsEnd() {} |
| 1052 | void BytecodeHandler::handleAlignment(unsigned numBytes) {} |
| 1053 | void BytecodeHandler::handleBlock( |
| 1054 | unsigned BType, const unsigned char* StartPtr, unsigned Size) {} |
| 1055 | void BytecodeHandler::handleVBR32(unsigned Size ) {} |
| 1056 | void BytecodeHandler::handleVBR64(unsigned Size ) {} |
| 1057 | |
Reid Spencer | dac69c8 | 2004-06-07 17:53:43 +0000 | [diff] [blame] | 1058 | // vim: sw=2 |