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 2994128..e367d02 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 3af40f2..f1dcf08 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 7e2c930..bac5a4c 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 a9b5e8d..1814077 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  | 
