#include "WriterInternals.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
+#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
typedef unsigned char uchar;
// outputInstructionFormat0 - Output those weird instructions that have a large
-// number of operands or have large operands themselves...
+// number of operands or have large operands themselves.
//
// Format: [opcode] [type] [numargs] [arg0] [arg1] ... [arg<numargs-1>]
//
output_typeid(Type); // Result type
unsigned NumArgs = I->getNumOperands();
- output_vbr(NumArgs + (isa<CastInst>(I) || isa<VANextInst>(I) ||
- isa<VAArgInst>(I)));
+ output_vbr(NumArgs + (isa<CastInst>(I) ||
+ isa<VAArgInst>(I) || Opcode == 56 || Opcode == 58));
if (!isa<GetElementPtrInst>(&I)) {
for (unsigned i = 0; i < NumArgs; ++i) {
int Slot = Table.getSlot(I->getType());
assert(Slot != -1 && "Cast return type unknown?");
output_typeid((unsigned)Slot);
- } else if (const VANextInst *VAI = dyn_cast<VANextInst>(I)) {
- int Slot = Table.getSlot(VAI->getArgType());
- assert(Slot != -1 && "VarArg argument type unknown?");
- output_typeid((unsigned)Slot);
+ } else if (Opcode == 56) { // Invoke escape sequence
+ output_vbr(cast<InvokeInst>(I)->getCallingConv());
+ } else if (Opcode == 58) { // Call escape sequence
+ output_vbr((cast<CallInst>(I)->getCallingConv() << 1) |
+ unsigned(cast<CallInst>(I)->isTailCall()));
}
-
} else {
int Slot = Table.getSlot(I->getOperand(0));
assert(Slot >= 0 && "No slot number for value!?!?");
}
void BytecodeWriter::outputInstruction(const Instruction &I) {
- assert(I.getOpcode() < 62 && "Opcode too big???");
+ assert(I.getOpcode() < 56 && "Opcode too big???");
unsigned Opcode = I.getOpcode();
unsigned NumOperands = I.getNumOperands();
- // Encode 'volatile load' as 62 and 'volatile store' as 63.
- if (isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile())
+ // Encode 'tail call' as 61, 'volatile load' as 62, and 'volatile store' as
+ // 63.
+ if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
+ if (CI->getCallingConv() == CallingConv::C) {
+ if (CI->isTailCall())
+ Opcode = 61; // CCC + Tail Call
+ else
+ ; // Opcode = Instruction::Call
+ } else if (CI->getCallingConv() == CallingConv::Fast) {
+ if (CI->isTailCall())
+ Opcode = 59; // FastCC + TailCall
+ else
+ Opcode = 60; // FastCC + Not Tail Call
+ } else {
+ Opcode = 58; // Call escape sequence.
+ }
+ } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
+ if (II->getCallingConv() == CallingConv::Fast)
+ Opcode = 57; // FastCC invoke.
+ else if (II->getCallingConv() != CallingConv::C)
+ Opcode = 56; // Invoke escape sequence.
+
+ } else if (isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) {
Opcode = 62;
- if (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile())
+ } else if (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) {
Opcode = 63;
+ }
// Figure out which type to encode with the instruction. Typically we want
// the type of the first parameter, as opposed to the type of the instruction
assert(Slots[1] != ~0U && "Cast return type unknown?");
if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1];
NumOperands++;
- } else if (const VANextInst *VANI = dyn_cast<VANextInst>(&I)) {
- Slots[1] = Table.getSlot(VANI->getArgType());
- assert(Slots[1] != ~0U && "va_next return type unknown?");
- if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1];
- NumOperands++;
} else if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
// We need to encode the type of sequential type indices into their slot #
unsigned Idx = 1;
Slots[Idx] = (Slots[Idx] << 2) | IdxId;
if (Slots[Idx] > MaxOpSlot) MaxOpSlot = Slots[Idx];
}
+ } else if (Opcode == 58) {
+ // If this is the escape sequence for call, emit the tailcall/cc info.
+ const CallInst &CI = cast<CallInst>(I);
+ ++NumOperands;
+ if (NumOperands < 3) {
+ Slots[NumOperands-1] = (CI.getCallingConv() << 1)|unsigned(CI.isTailCall());
+ if (Slots[NumOperands-1] > MaxOpSlot)
+ MaxOpSlot = Slots[NumOperands-1];
+ }
+ } else if (Opcode == 56) {
+ // Invoke escape seq has at least 4 operands to encode.
+ ++NumOperands;
}
// Decide which instruction encoding to use. This is determined primarily
}
}
-static inline bool hasNullValue(unsigned TyID) {
- return TyID != Type::LabelTyID && TyID != Type::VoidTyID;
+static inline bool hasNullValue(const Type *Ty) {
+ return Ty != Type::LabelTy && Ty != Type::VoidTy && !isa<OpaqueType>(Ty);
}
void BytecodeWriter::outputConstants(bool isFunction) {
if (isFunction) // Don't re-emit module constants
ValNo += Table.getModuleLevel(pno);
- if (hasNullValue(pno)) {
+ if (hasNullValue(Plane[0]->getType())) {
// Skip zero initializer
if (ValNo == 0)
ValNo = 1;
BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfoBlockID, *this);
// Output the types for the global variables in the module...
- for (Module::const_global_iterator I = M->global_begin(), End = M->global_end(); I != End;++I) {
+ for (Module::const_global_iterator I = M->global_begin(),
+ End = M->global_end(); I != End;++I) {
int Slot = Table.getSlot(I->getType());
assert(Slot != -1 && "Module global vars is broken!");
assert(Slot != -1 && "Module slot calculator is broken!");
assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
assert(((Slot << 5) >> 5) == Slot && "Slot # too big!");
- unsigned ID = (Slot << 5) + 1;
+ unsigned ID = (Slot << 5);
+
+ if (I->getCallingConv() < 15)
+ ID += I->getCallingConv()+1;
+
if (I->isExternal()) // If external, we don't have an FunctionInfo block.
ID |= 1 << 4;
output_vbr(ID);
+
+ if (I->getCallingConv() >= 15)
+ output_vbr(I->getCallingConv());
}
output_vbr((unsigned)Table.getSlot(Type::VoidTy) << 5);
Out.flush();
}
-// vim: sw=2 ai