diff options
Diffstat (limited to 'lib/Bytecode')
-rw-r--r-- | lib/Bytecode/Reader/ConstantReader.cpp | 10 | ||||
-rw-r--r-- | lib/Bytecode/Reader/InstructionReader.cpp | 54 | ||||
-rw-r--r-- | lib/Bytecode/Writer/ConstantWriter.cpp | 8 | ||||
-rw-r--r-- | lib/Bytecode/Writer/InstructionWriter.cpp | 53 |
4 files changed, 98 insertions, 27 deletions
diff --git a/lib/Bytecode/Reader/ConstantReader.cpp b/lib/Bytecode/Reader/ConstantReader.cpp index 2994128f7d..e367d02e7c 100644 --- a/lib/Bytecode/Reader/ConstantReader.cpp +++ b/lib/Bytecode/Reader/ConstantReader.cpp @@ -33,15 +33,15 @@ bool BytecodeParser::parseTypeConstant(const uchar *&Buf, const uchar *EndBuf, const Type *RetType = getType(Typ); if (RetType == 0) return true; - MethodType::ParamTypes Params; + unsigned NumParams; + if (read_vbr(Buf, EndBuf, NumParams)) return true; - if (read_vbr(Buf, EndBuf, Typ)) return true; - while (Typ) { + MethodType::ParamTypes Params; + while (NumParams--) { + if (read_vbr(Buf, EndBuf, Typ)) return true; const Type *Ty = getType(Typ); if (Ty == 0) return true; Params.push_back(Ty); - - if (read_vbr(Buf, EndBuf, Typ)) return true; } Val = MethodType::getMethodType(RetType, Params); diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp index 3af40f2d81..f1dcf08e79 100644 --- a/lib/Bytecode/Reader/InstructionReader.cpp +++ b/lib/Bytecode/Reader/InstructionReader.cpp @@ -196,30 +196,48 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf, Method *M = (Method*)getValue(Raw.Ty, Raw.Arg1); if (M == 0) return true; + vector<Value *> Params; const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes(); - MethodType::ParamTypes::const_iterator It = PL.begin(); - vector<Value *> Params; - switch (Raw.NumOperands) { - case 0: cerr << "Invalid call instruction encountered!\n"; - return true; - case 1: break; - case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break; - case 3: Params.push_back(getValue(*It++, Raw.Arg2)); - if (It == PL.end()) return true; - Params.push_back(getValue(*It++, Raw.Arg3)); break; - default: - Params.push_back(getValue(*It++, Raw.Arg2)); - { - vector<unsigned> &args = *Raw.VarArgs; - for (unsigned i = 0; i < args.size(); i++) { - if (It == PL.end()) return true; - Params.push_back(getValue(*It++, args[i])); + if (!M->getType()->isMethodType()->isVarArg()) { + MethodType::ParamTypes::const_iterator It = PL.begin(); + + switch (Raw.NumOperands) { + case 0: cerr << "Invalid call instruction encountered!\n"; + return true; + case 1: break; + case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break; + case 3: Params.push_back(getValue(*It++, Raw.Arg2)); + if (It == PL.end()) return true; + Params.push_back(getValue(*It++, Raw.Arg3)); break; + default: + Params.push_back(getValue(*It++, Raw.Arg2)); + { + vector<unsigned> &args = *Raw.VarArgs; + for (unsigned i = 0; i < args.size(); i++) { + if (It == PL.end()) return true; + // TODO: Check getValue for null! + Params.push_back(getValue(*It++, args[i])); + } } + delete Raw.VarArgs; + } + if (It != PL.end()) return true; + } else { + // The first parameter does not have a type specifier... because there + // must be at least one concrete argument to a vararg type... + Params.push_back(getValue(PL.front(), Raw.Arg2)); + + vector<unsigned> &args = *Raw.VarArgs; + if ((args.size() & 1) != 0) return true; // Must be pairs of type/value + for (unsigned i = 0; i < args.size(); i+=2) { + Value *Ty = getValue(Type::TypeTy, args[i]); + if (!Ty) return true; + // TODO: Check getValue for null! + Params.push_back(getValue(Ty->castTypeAsserting(), args[i+1])); } delete Raw.VarArgs; } - if (It != PL.end()) return true; Res = new CallInst(M, Params); return false; diff --git a/lib/Bytecode/Writer/ConstantWriter.cpp b/lib/Bytecode/Writer/ConstantWriter.cpp index 7e2c9307b9..bac5a4c050 100644 --- a/lib/Bytecode/Writer/ConstantWriter.cpp +++ b/lib/Bytecode/Writer/ConstantWriter.cpp @@ -28,6 +28,9 @@ void BytecodeWriter::outputType(const Type *T) { assert(Slot != -1 && "Type used but not available!!"); output_vbr((unsigned)Slot, Out); + // Output the number of arguments to method (+1 if varargs): + output_vbr(MT->getParamTypes().size()+MT->isVarArg(), Out); + // Output all of the arguments... MethodType::ParamTypes::const_iterator I = MT->getParamTypes().begin(); for (; I != MT->getParamTypes().end(); ++I) { @@ -36,8 +39,9 @@ void BytecodeWriter::outputType(const Type *T) { output_vbr((unsigned)Slot, Out); } - // Terminate list with VoidTy - output_vbr((unsigned)Type::VoidTy->getPrimitiveID(), Out); + // Terminate list with VoidTy if we are a varargs function... + if (MT->isVarArg()) + output_vbr((unsigned)Type::VoidTy->getPrimitiveID(), Out); break; } diff --git a/lib/Bytecode/Writer/InstructionWriter.cpp b/lib/Bytecode/Writer/InstructionWriter.cpp index a9b5e8d304..18140772a3 100644 --- a/lib/Bytecode/Writer/InstructionWriter.cpp +++ b/lib/Bytecode/Writer/InstructionWriter.cpp @@ -35,8 +35,53 @@ static void outputInstructionFormat0(const Instruction *I, output_vbr(NumArgs, Out); for (unsigned i = 0; i < NumArgs; ++i) { - const Value *N = I->getOperand(i); - int Slot = Table.getValSlot(N); + int Slot = Table.getValSlot(I->getOperand(i)); + assert(Slot >= 0 && "No slot number for value!?!?"); + output_vbr((unsigned)Slot, Out); + } + align32(Out); // We must maintain correct alignment! +} + + +// outputInstrVarArgsCall - Output the obsurdly annoying varargs method calls. +// This are more annoying than most because the signature of the call does not +// tell us anything about the types of the arguments in the varargs portion. +// Because of this, we encode (as type 0) all of the argument types explicitly +// before the argument value. This really sucks, but you shouldn't be using +// varargs functions in your code! *death to printf*! +// +// Format: [opcode] [type] [numargs] [arg0] [arg1] ... [arg<numargs-1>] +// +static void outputInstrVarArgsCall(const Instruction *I, + const SlotCalculator &Table, unsigned Type, + vector<uchar> &Out) { + assert(I->getOpcode() == Instruction::Call /*|| + I->getOpcode() == Instruction::ICall */); + // Opcode must have top two bits clear... + output_vbr(I->getOpcode(), Out); // Instruction Opcode ID + output_vbr(Type, Out); // Result type (varargs type) + + unsigned NumArgs = I->getNumOperands(); + output_vbr((NumArgs-2)*2+2, Out); // Don't duplicate method & Arg1 types + + // Output the method type without an extra type argument. + int Slot = Table.getValSlot(I->getOperand(0)); + assert(Slot >= 0 && "No slot number for value!?!?"); + output_vbr((unsigned)Slot, Out); + + // VarArgs methods must have at least one specified operand + Slot = Table.getValSlot(I->getOperand(1)); + assert(Slot >= 0 && "No slot number for value!?!?"); + output_vbr((unsigned)Slot, Out); + + for (unsigned i = 2; i < NumArgs; ++i) { + // Output Arg Type ID + Slot = Table.getValSlot(I->getOperand(i)->getType()); + assert(Slot >= 0 && "No slot number for value!?!?"); + output_vbr((unsigned)Slot, Out); + + // Output arg ID itself + Slot = Table.getValSlot(I->getOperand(i)); assert(Slot >= 0 && "No slot number for value!?!?"); output_vbr((unsigned)Slot, Out); } @@ -161,6 +206,10 @@ bool BytecodeWriter::processInstruction(const Instruction *I) { assert(Slots[1] != -1 && "Cast return type unknown?"); if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1]; NumOperands++; + } else if (I->getOpcode() == Instruction::Call && // Handle VarArg calls + I->getOperand(0)->getType()->isMethodType()->isVarArg()) { + outputInstrVarArgsCall(I, Table, Type, Out); + return false; } // Decide which instruction encoding to use. This is determined primarily by |