Add support for extern varargs methods & varargs method calls
[oota-llvm.git] / lib / Bytecode / Reader / InstructionReader.cpp
1 //===- ReadInst.cpp - Code to read an instruction from bytecode -------------===
2 //
3 // This file defines the mechanism to read an instruction from a bytecode 
4 // stream.
5 //
6 // Note that this library should be as fast as possible, reentrant, and 
7 // threadsafe!!
8 //
9 // TODO: Change from getValue(Raw.Arg1) etc, to getArg(Raw, 1)
10 //       Make it check type, so that casts are checked.
11 //
12 //===------------------------------------------------------------------------===
13
14 #include "llvm/iOther.h"
15 #include "llvm/iTerminators.h"
16 #include "llvm/iMemory.h"
17 #include "llvm/DerivedTypes.h"
18 #include "ReaderInternals.h"
19
20 bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf, 
21                                   RawInst &Result) {
22   unsigned Op, Typ;
23   if (read(Buf, EndBuf, Op)) return true;
24
25   Result.NumOperands =  Op >> 30;
26   Result.Opcode      = (Op >> 24) & 63;
27
28   switch (Result.NumOperands) {
29   case 1:
30     Result.Ty   = getType((Op >> 12) & 4095);
31     Result.Arg1 = Op & 4095;
32     if (Result.Arg1 == 4095)    // Handle special encoding for 0 operands...
33       Result.NumOperands = 0;
34     break;
35   case 2:
36     Result.Ty   = getType((Op >> 16) & 255);
37     Result.Arg1 = (Op >> 8 ) & 255;
38     Result.Arg2 = (Op >> 0 ) & 255;
39     break;
40   case 3:
41     Result.Ty   = getType((Op >> 18) & 63);
42     Result.Arg1 = (Op >> 12) & 63;
43     Result.Arg2 = (Op >> 6 ) & 63;
44     Result.Arg3 = (Op >> 0 ) & 63;
45     break;
46   case 0:
47     Buf -= 4;  // Hrm, try this again...
48     if (read_vbr(Buf, EndBuf, Result.Opcode)) return true;
49     if (read_vbr(Buf, EndBuf, Typ)) return true;
50     Result.Ty = getType(Typ);
51     if (read_vbr(Buf, EndBuf, Result.NumOperands)) return true;
52
53     switch (Result.NumOperands) {
54     case 0: 
55       cerr << "Zero Arg instr found!\n"; 
56       return true;  // This encoding is invalid!
57     case 1: 
58       if (read_vbr(Buf, EndBuf, Result.Arg1)) return true;
59       break;
60     case 2:
61       if (read_vbr(Buf, EndBuf, Result.Arg1) || 
62           read_vbr(Buf, EndBuf, Result.Arg2)) return true;
63       break;
64     case 3:
65       if (read_vbr(Buf, EndBuf, Result.Arg1) || 
66           read_vbr(Buf, EndBuf, Result.Arg2) ||
67           read_vbr(Buf, EndBuf, Result.Arg3)) return true;
68       break;
69     default:
70       if (read_vbr(Buf, EndBuf, Result.Arg1) || 
71           read_vbr(Buf, EndBuf, Result.Arg2)) return true;
72
73       // Allocate a vector to hold arguments 3, 4, 5, 6 ...
74       Result.VarArgs = new vector<unsigned>(Result.NumOperands-2);
75       for (unsigned a = 0; a < Result.NumOperands-2; a++)
76         if (read_vbr(Buf, EndBuf, (*Result.VarArgs)[a])) return true;
77       break;
78     }
79     if (align32(Buf, EndBuf)) return true;
80     break;
81   }
82
83 #if 0
84   cerr << "NO: "  << Result.NumOperands   << " opcode: " << Result.Opcode 
85        << " Ty: " << Result.Ty->getName() << " arg1: "   << Result.Arg1 
86        << " arg2: "   << Result.Arg2 << " arg3: "   << Result.Arg3 << endl;
87 #endif
88   return false;
89 }
90
91
92 bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
93                                       Instruction *&Res) {
94   RawInst Raw;
95   if (ParseRawInst(Buf, EndBuf, Raw)) return true;;
96
97   if (Raw.Opcode >= Instruction::FirstUnaryOp && 
98       Raw.Opcode <  Instruction::NumUnaryOps  && Raw.NumOperands == 1) {
99     Res = UnaryOperator::create((Instruction::UnaryOps)Raw.Opcode,
100                                 getValue(Raw.Ty,Raw.Arg1));
101     return false;
102   } else if (Raw.Opcode >= Instruction::FirstBinaryOp &&
103              Raw.Opcode <  Instruction::NumBinaryOps  && Raw.NumOperands == 2) {
104     Res = BinaryOperator::create((Instruction::BinaryOps)Raw.Opcode,
105                                  getValue(Raw.Ty, Raw.Arg1),
106                                  getValue(Raw.Ty, Raw.Arg2));
107     return false;
108   } 
109
110   Value *V;
111   switch (Raw.Opcode) {
112   case Instruction::Cast:
113     Res = new CastInst(getValue(Raw.Ty, Raw.Arg1), getType(Raw.Arg2));
114     return false;
115
116   case Instruction::PHINode: {
117     PHINode *PN = new PHINode(Raw.Ty);
118     switch (Raw.NumOperands) {
119     case 0: 
120     case 1: 
121     case 3: cerr << "Invalid phi node encountered!\n"; 
122             delete PN; 
123             return true;
124     case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1),
125                             (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2)); 
126       break;
127     default:
128       PN->addIncoming(getValue(Raw.Ty, Raw.Arg1), 
129                       (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2));
130       if (Raw.VarArgs->size() & 1) {
131         cerr << "PHI Node with ODD number of arguments!\n";
132         delete PN;
133         return true;
134       } else {
135         vector<unsigned> &args = *Raw.VarArgs;
136         for (unsigned i = 0; i < args.size(); i+=2)
137           PN->addIncoming(getValue(Raw.Ty, args[i]),
138                           (BasicBlock*)getValue(Type::LabelTy, args[i+1]));
139       }
140       delete Raw.VarArgs; 
141       break;
142     }
143     Res = PN;
144     return false;
145   }
146
147   case Instruction::Shl:
148   case Instruction::Shr:
149     Res = new ShiftInst((Instruction::OtherOps)Raw.Opcode,
150                         getValue(Raw.Ty, Raw.Arg1),
151                         getValue(Type::UByteTy, Raw.Arg2));
152     return false;
153   case Instruction::Ret:
154     if (Raw.NumOperands == 0) {
155       Res = new ReturnInst(); return false; 
156     } else if (Raw.NumOperands == 1) {
157       Res = new ReturnInst(getValue(Raw.Ty, Raw.Arg1)); return false; 
158     }
159     break;
160
161   case Instruction::Br:
162     if (Raw.NumOperands == 1) {
163       Res = new BranchInst((BasicBlock*)getValue(Type::LabelTy, Raw.Arg1));
164       return false;
165     } else if (Raw.NumOperands == 3) {
166       Res = new BranchInst((BasicBlock*)getValue(Type::LabelTy, Raw.Arg1),
167                            (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2),
168                                         getValue(Type::BoolTy , Raw.Arg3));
169       return false;
170     }
171     break;
172     
173   case Instruction::Switch: {
174     SwitchInst *I = 
175       new SwitchInst(getValue(Raw.Ty, Raw.Arg1), 
176                      (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2));
177     Res = I;
178     if (Raw.NumOperands < 3) return false;  // No destinations?  Wierd.
179
180     if (Raw.NumOperands == 3 || Raw.VarArgs->size() & 1) {
181       cerr << "Switch statement with odd number of arguments!\n";
182       delete I;
183       return true;
184     }      
185     
186     vector<unsigned> &args = *Raw.VarArgs;
187     for (unsigned i = 0; i < args.size(); i += 2)
188       I->dest_push_back((ConstPoolVal*)getValue(Raw.Ty, args[i]),
189                         (BasicBlock*)getValue(Type::LabelTy, args[i+1]));
190
191     delete Raw.VarArgs;
192     return false;
193   }
194
195   case Instruction::Call: {
196     Method *M = (Method*)getValue(Raw.Ty, Raw.Arg1);
197     if (M == 0) return true;
198
199     vector<Value *> Params;
200     const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes();
201
202     if (!M->getType()->isMethodType()->isVarArg()) {
203       MethodType::ParamTypes::const_iterator It = PL.begin();
204
205       switch (Raw.NumOperands) {
206       case 0: cerr << "Invalid call instruction encountered!\n";
207         return true;
208       case 1: break;
209       case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break;
210       case 3: Params.push_back(getValue(*It++, Raw.Arg2)); 
211         if (It == PL.end()) return true;
212         Params.push_back(getValue(*It++, Raw.Arg3)); break;
213       default:
214         Params.push_back(getValue(*It++, Raw.Arg2));
215         {
216           vector<unsigned> &args = *Raw.VarArgs;
217           for (unsigned i = 0; i < args.size(); i++) {
218             if (It == PL.end()) return true;
219             // TODO: Check getValue for null!
220             Params.push_back(getValue(*It++, args[i]));
221           }
222         }
223         delete Raw.VarArgs;
224       }
225       if (It != PL.end()) return true;
226     } else {
227       // The first parameter does not have a type specifier... because there
228       // must be at least one concrete argument to a vararg type...
229       Params.push_back(getValue(PL.front(), Raw.Arg2));
230
231       vector<unsigned> &args = *Raw.VarArgs;
232       if ((args.size() & 1) != 0) return true;  // Must be pairs of type/value
233       for (unsigned i = 0; i < args.size(); i+=2) {
234         Value *Ty = getValue(Type::TypeTy, args[i]);
235         if (!Ty) return true;
236         // TODO: Check getValue for null!
237         Params.push_back(getValue(Ty->castTypeAsserting(), args[i+1]));
238       }
239       delete Raw.VarArgs;
240     }
241
242     Res = new CallInst(M, Params);
243     return false;
244   }
245   case Instruction::Malloc:
246     if (Raw.NumOperands > 2) return true;
247     V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
248     Res = new MallocInst(Raw.Ty, V);
249     return false;
250
251   case Instruction::Alloca:
252     if (Raw.NumOperands > 2) return true;
253     V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
254     Res = new AllocaInst(Raw.Ty, V);
255     return false;
256
257   case Instruction::Free:
258     V = getValue(Raw.Ty, Raw.Arg1);
259     if (!V->getType()->isPointerType()) return true;
260     Res = new FreeInst(V);
261     return false;
262
263   case Instruction::Load:
264   case Instruction::GetElementPtr: {
265     vector<ConstPoolVal*> Idx;
266     switch (Raw.NumOperands) {
267     case 0: cerr << "Invalid load encountered!\n"; return true;
268     case 1: break;
269     case 2: V = getValue(Type::UByteTy, Raw.Arg2);
270             if (!V->isConstant()) return true;
271             Idx.push_back(V->castConstant());
272             break;
273     case 3: V = getValue(Type::UByteTy, Raw.Arg2);
274             if (!V->isConstant()) return true;
275             Idx.push_back(V->castConstant());
276             V = getValue(Type::UByteTy, Raw.Arg3);
277             if (!V->isConstant()) return true;
278             Idx.push_back(V->castConstant());
279             break;
280     default:
281       V = getValue(Type::UByteTy, Raw.Arg2);
282       if (!V->isConstant()) return true;
283       Idx.push_back(V->castConstant());
284       vector<unsigned> &args = *Raw.VarArgs;
285       for (unsigned i = 0, E = args.size(); i != E; ++i) {
286         V = getValue(Type::UByteTy, args[i]);
287         if (!V->isConstant()) return true;
288         Idx.push_back(V->castConstant());
289       }
290       delete Raw.VarArgs; 
291       break;
292     }
293     if (Raw.Opcode == Instruction::Load)
294       Res = new LoadInst(getValue(Raw.Ty, Raw.Arg1), Idx);
295     else if (Raw.Opcode == Instruction::GetElementPtr)
296       Res = new GetElementPtrInst(getValue(Raw.Ty, Raw.Arg1), Idx);
297     else
298       abort();
299     return false;
300   }
301   case Instruction::Store: {
302     vector<ConstPoolVal*> Idx;
303     switch (Raw.NumOperands) {
304     case 0: 
305     case 1: cerr << "Invalid store encountered!\n"; return true;
306     case 2: break;
307     case 3: V = getValue(Type::UByteTy, Raw.Arg3);
308             if (!V->isConstant()) return true;
309             Idx.push_back(V->castConstant());
310             break;
311     default:
312       vector<unsigned> &args = *Raw.VarArgs;
313       for (unsigned i = 0, E = args.size(); i != E; ++i) {
314         V = getValue(Type::UByteTy, args[i]);
315         if (!V->isConstant()) return true;
316         Idx.push_back(V->castConstant());
317       }
318       delete Raw.VarArgs; 
319       break;
320     }
321
322     const Type *ElType = StoreInst::getIndexedType(Raw.Ty, Idx);
323     if (ElType == 0) return true;
324     Res = new StoreInst(getValue(ElType, Raw.Arg1), getValue(Raw.Ty, Raw.Arg2),
325                         Idx);
326     return false;
327   }
328   }  // end switch(Raw.Opcode) 
329
330   cerr << "Unrecognized instruction! " << Raw.Opcode 
331        << " ADDR = 0x" << (void*)Buf << endl;
332   return true;
333 }