From eff112c6c3d018ac97522618e71c8c0956c451ee Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 18 Oct 2003 05:54:48 +0000 Subject: [PATCH] Updated to emit the final 1.0 bytecode format. This supports weak linkage, more efficient encoding of varargs calls, and the new varargs intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9221 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bytecode/Writer/InstructionWriter.cpp | 60 +++++++++++++++-------- lib/Bytecode/Writer/Writer.cpp | 4 +- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/lib/Bytecode/Writer/InstructionWriter.cpp b/lib/Bytecode/Writer/InstructionWriter.cpp index d5a2abf3fb3..57012c9df93 100644 --- a/lib/Bytecode/Writer/InstructionWriter.cpp +++ b/lib/Bytecode/Writer/InstructionWriter.cpp @@ -30,7 +30,8 @@ static void outputInstructionFormat0(const Instruction *I, unsigned Opcode, output_vbr(Type, Out); // Result type unsigned NumArgs = I->getNumOperands(); - output_vbr(NumArgs + (isa(I) || isa(I)), Out); + output_vbr(NumArgs + (isa(I) || isa(I) || + isa(I)), Out); for (unsigned i = 0; i < NumArgs; ++i) { int Slot = Table.getSlot(I->getOperand(i)); @@ -38,9 +39,13 @@ static void outputInstructionFormat0(const Instruction *I, unsigned Opcode, output_vbr((unsigned)Slot, Out); } - if (isa(I) || isa(I)) { + if (isa(I) || isa(I)) { int Slot = Table.getSlot(I->getType()); - assert(Slot != -1 && "Cast/VarArg return type unknown?"); + assert(Slot != -1 && "Cast return type unknown?"); + output_vbr((unsigned)Slot, Out); + } else if (const VANextInst *VAI = dyn_cast(I)) { + int Slot = Table.getSlot(VAI->getArgType()); + assert(Slot != -1 && "VarArg argument type unknown?"); output_vbr((unsigned)Slot, Out); } @@ -65,29 +70,37 @@ static void outputInstrVarArgsCall(const Instruction *I, unsigned Opcode, output_vbr(Opcode << 2, Out); // Instruction Opcode ID output_vbr(Type, Out); // Result type (varargs type) - unsigned NumArgs = I->getNumOperands(); - output_vbr(NumArgs*2, Out); - // TODO: Don't need to emit types for the fixed types of the varargs function - // prototype... + const PointerType *PTy = cast(I->getOperand(0)->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + unsigned NumParams = FTy->getNumParams(); + + unsigned NumFixedOperands; + if (isa(I)) { + // Output an operand for the callee and each fixed argument, then two for + // each variable argument. + NumFixedOperands = 1+NumParams; + } else { + assert(isa(I) && "Not call or invoke??"); + // Output an operand for the callee and destinations, then two for each + // variable argument. + NumFixedOperands = 3+NumParams; + } + output_vbr(2 * I->getNumOperands()-NumFixedOperands, Out); // The type for the function has already been emitted in the type field of the // instruction. Just emit the slot # now. - int Slot = Table.getSlot(I->getOperand(0)); - assert(Slot >= 0 && "No slot number for value!?!?"); - output_vbr((unsigned)Slot, Out); - - // Output a dummy field to fill Arg#2 in the reader that is currently unused - // for varargs calls. This is a gross hack to make the code simpler, but we - // aren't really doing very small bytecode for varargs calls anyways. - // FIXME in the future: Smaller bytecode for varargs calls - output_vbr(0, Out); - - for (unsigned i = 1; i < NumArgs; ++i) { - // Output Arg Type ID - Slot = Table.getSlot(I->getOperand(i)->getType()); + for (unsigned i = 0; i != NumFixedOperands; ++i) { + int Slot = Table.getSlot(I->getOperand(i)); assert(Slot >= 0 && "No slot number for value!?!?"); output_vbr((unsigned)Slot, Out); + } + for (unsigned i = NumFixedOperands, e = I->getNumOperands(); i != e; ++i) { + // Output Arg Type ID + int Slot = Table.getSlot(I->getOperand(i)->getType()); + assert(Slot >= 0 && "No slot number for value!?!?"); + output_vbr((unsigned)Slot, Out); + // Output arg ID itself Slot = Table.getSlot(I->getOperand(i)); assert(Slot >= 0 && "No slot number for value!?!?"); @@ -214,13 +227,18 @@ void BytecodeWriter::processInstruction(const Instruction &I) { if (Slot > MaxOpSlot) MaxOpSlot = Slot; // Handle the special case for cast... - if (isa(I) || isa(I)) { + if (isa(I) || isa(I)) { // Cast has to encode the destination type as the second argument in the // packet, or else we won't know what type to cast to! Slots[1] = Table.getSlot(I.getType()); assert(Slots[1] != -1 && "Cast return type unknown?"); if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1]; NumOperands++; + } else if (const VANextInst *VANI = dyn_cast(&I)) { + Slots[1] = Table.getSlot(VANI->getArgType()); + assert(Slots[1] != -1 && "va_next return type unknown?"); + if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1]; + NumOperands++; } else if (const CallInst *CI = dyn_cast(&I)){// Handle VarArg calls const PointerType *Ty = cast(CI->getCalledValue()->getType()); if (cast(Ty->getElementType())->isVarArg()) { diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index 0304ab6d4fb..09684614567 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -48,8 +48,8 @@ BytecodeWriter::BytecodeWriter(std::deque &o, const Module *M) bool hasNoEndianness = M->getEndianness() == Module::AnyEndianness; bool hasNoPointerSize = M->getPointerSize() == Module::AnyPointerSize; - // Output the version identifier... we are currently on bytecode version #2 - unsigned Version = (2 << 4) | isBigEndian | (hasLongPointers << 1) | + // Output the version identifier... we are currently on bytecode version #0 + unsigned Version = (0 << 4) | isBigEndian | (hasLongPointers << 1) | (hasNoEndianness << 2) | (hasNoPointerSize << 3); output_vbr(Version, Out); align32(Out);