Initial revision
[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   //cerr << "NO: "  << Result.NumOperands   << " opcode: " << Result.Opcode 
84   //   << " Ty: " << Result.Ty->getName() << " arg1: "   << Result.Arg1 << endl;
85   return false;
86 }
87
88
89 bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
90                                       Instruction *&Res) {
91   RawInst Raw;
92   if (ParseRawInst(Buf, EndBuf, Raw)) return true;;
93
94   if (Raw.Opcode >= Instruction::FirstUnaryOp && 
95       Raw.Opcode <  Instruction::NumUnaryOps  && Raw.NumOperands == 1) {
96     Res = Instruction::getUnaryOperator(Raw.Opcode, getValue(Raw.Ty, Raw.Arg1));
97     return false;
98   } else if (Raw.Opcode >= Instruction::FirstBinaryOp &&
99              Raw.Opcode <  Instruction::NumBinaryOps  && Raw.NumOperands == 2) {
100     Res = Instruction::getBinaryOperator(Raw.Opcode, getValue(Raw.Ty, Raw.Arg1),
101                                          getValue(Raw.Ty, Raw.Arg2));
102     return false;
103   } else if (Raw.Opcode == Instruction::PHINode) {
104     PHINode *PN = new PHINode(Raw.Ty);
105     switch (Raw.NumOperands) {
106     case 0: cerr << "Invalid phi node encountered!\n"; 
107             delete PN; 
108             return true;
109     case 1: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1)); break;
110     case 2: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1)); 
111             PN->addIncoming(getValue(Raw.Ty, Raw.Arg2)); break;
112     case 3: PN->addIncoming(getValue(Raw.Ty, Raw.Arg1)); 
113             PN->addIncoming(getValue(Raw.Ty, Raw.Arg2)); 
114             PN->addIncoming(getValue(Raw.Ty, Raw.Arg3)); break;
115     default:
116       PN->addIncoming(getValue(Raw.Ty, Raw.Arg1)); 
117       PN->addIncoming(getValue(Raw.Ty, Raw.Arg2));
118       {
119         vector<unsigned> &args = *Raw.VarArgs;
120         for (unsigned i = 0; i < args.size(); i++)
121           PN->addIncoming(getValue(Raw.Ty, args[i]));
122       }
123       delete Raw.VarArgs;
124     }
125     Res = PN;
126     return false;
127   } else if (Raw.Opcode == Instruction::Ret) {
128     if (Raw.NumOperands == 0) {
129       Res = new ReturnInst(); return false; 
130     } else if (Raw.NumOperands == 1) {
131       Res = new ReturnInst(getValue(Raw.Ty, Raw.Arg1)); return false; 
132     }
133   } else if (Raw.Opcode == Instruction::Br) {
134     if (Raw.NumOperands == 1) {
135       Res = new BranchInst((BasicBlock*)getValue(Type::LabelTy, Raw.Arg1));
136       return false;
137     } else if (Raw.NumOperands == 3) {
138       Res = new BranchInst((BasicBlock*)getValue(Type::LabelTy, Raw.Arg1),
139                            (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2),
140                                         getValue(Type::BoolTy , Raw.Arg3));
141       return false;
142     }
143   } else if (Raw.Opcode == Instruction::Switch) {
144     SwitchInst *I = 
145       new SwitchInst(getValue(Raw.Ty, Raw.Arg1), 
146                      (BasicBlock*)getValue(Type::LabelTy, Raw.Arg2));
147     Res = I;
148     if (Raw.NumOperands < 3) return false;  // No destinations?  Wierd.
149
150     if (Raw.NumOperands == 3 || Raw.VarArgs->size() & 1) {
151       cerr << "Switch statement with odd number of arguments!\n";
152       delete I;
153       return true;
154     }      
155     
156     vector<unsigned> &args = *Raw.VarArgs;
157     for (unsigned i = 0; i < args.size(); i += 2)
158       I->dest_push_back((ConstPoolVal*)getValue(Raw.Ty, args[i]),
159                         (BasicBlock*)getValue(Type::LabelTy, args[i+1]));
160
161     delete Raw.VarArgs;
162     return false;
163   } else if (Raw.Opcode == Instruction::Call) {
164     Method *M = (Method*)getValue(Raw.Ty, Raw.Arg1);
165     if (M == 0) return true;
166
167     const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes();
168     MethodType::ParamTypes::const_iterator It = PL.begin();
169
170     vector<Value *> Params;
171     switch (Raw.NumOperands) {
172     case 0: cerr << "Invalid call instruction encountered!\n";
173             return true;
174     case 1: break;
175     case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break;
176     case 3: Params.push_back(getValue(*It++, Raw.Arg2)); 
177             if (It == PL.end()) return true;
178             Params.push_back(getValue(*It++, Raw.Arg3)); break;
179     default:
180       Params.push_back(getValue(*It++, Raw.Arg2));
181       {
182         vector<unsigned> &args = *Raw.VarArgs;
183         for (unsigned i = 0; i < args.size(); i++) {
184           if (It == PL.end()) return true;
185           Params.push_back(getValue(*It++, args[i]));
186         }
187       }
188       delete Raw.VarArgs;
189     }
190     if (It != PL.end()) return true;
191
192     Res = new CallInst(M, Params);
193     return false;
194   } else if (Raw.Opcode == Instruction::Malloc) {
195     if (Raw.NumOperands > 2) return true;
196     Value *Sz = (Raw.NumOperands == 2) ? getValue(Type::UIntTy, Raw.Arg2) : 0;
197     Res = new MallocInst((ConstPoolType*)getValue(Type::TypeTy, Raw.Arg1), Sz);
198     return false;
199   } else if (Raw.Opcode == Instruction::Alloca) {
200     if (Raw.NumOperands > 2) return true;
201     Value *Sz = (Raw.NumOperands == 2) ? getValue(Type::UIntTy, Raw.Arg2) : 0;
202     Res = new AllocaInst((ConstPoolType*)getValue(Type::TypeTy, Raw.Arg1), Sz);
203     return false;
204   } else if (Raw.Opcode == Instruction::Free) {
205     Value *Val = getValue(Raw.Ty, Raw.Arg1);
206     if (!Val->getType()->isPointerType()) return true;
207     Res = new FreeInst(Val);
208     return false;
209   }
210
211   cerr << "Unrecognized instruction! " << Raw.Opcode << endl;
212   return true;
213 }