//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "bytecodewriter"
+#define DEBUG_TYPE "bcwriter"
#include "WriterInternals.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/ParameterAttributes.h"
#include "llvm/InlineAsm.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
-#include "llvm/SymbolTable.h"
#include "llvm/TypeSymbolTable.h"
+#include "llvm/ValueSymbolTable.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/Compressor.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Streams.h"
#include "llvm/System/Program.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include <cstring>
}
}
-inline void BytecodeWriter::output(int i) {
- output((unsigned)i);
+inline void BytecodeWriter::output(int32_t i) {
+ output((uint32_t)i);
}
/// output_vbr - Output an unsigned value, by using the least number of bytes
}
}
-inline void BytecodeWriter::output_vbr(unsigned i) {
+inline void BytecodeWriter::output_vbr(uint32_t i) {
while (1) {
if (i < 0x80) { // done?
Out.push_back((unsigned char)i); // We know the high bit is clear...
output_vbr((unsigned)i << 1); // Low order bit is clear.
}
-inline void BytecodeWriter::output(const std::string &s) {
- unsigned Len = s.length();
+inline void BytecodeWriter::output_str(const char *Str, unsigned Len) {
output_vbr(Len); // Strings may have an arbitrary length.
- Out.insert(Out.end(), s.begin(), s.end());
+ Out.insert(Out.end(), Str, Str+Len);
}
inline void BytecodeWriter::output_data(const void *Ptr, const void *End) {
//=== Constant Output ===//
//===----------------------------------------------------------------------===//
+void BytecodeWriter::outputParamAttrsList(const ParamAttrsList *Attrs) {
+ if (!Attrs) {
+ output_vbr(unsigned(0));
+ return;
+ }
+ unsigned numAttrs = Attrs->size();
+ output_vbr(numAttrs);
+ for (unsigned i = 0; i < numAttrs; ++i) {
+ uint16_t index = Attrs->getParamIndex(i);
+ uint16_t attrs = Attrs->getParamAttrs(index);
+ output_vbr(uint32_t(index));
+ output_vbr(uint32_t(attrs));
+ }
+}
+
void BytecodeWriter::outputType(const Type *T) {
const StructType* STy = dyn_cast<StructType>(T);
if(STy && STy->isPacked())
output_vbr(cast<IntegerType>(T)->getBitWidth());
break;
case Type::FunctionTyID: {
- const FunctionType *MT = cast<FunctionType>(T);
- int Slot = Table.getSlot(MT->getReturnType());
- assert(Slot != -1 && "Type used but not available!!");
- output_typeid((unsigned)Slot);
- output_vbr(unsigned(MT->getParamAttrs(0)));
+ const FunctionType *FT = cast<FunctionType>(T);
+ output_typeid(Table.getTypeSlot(FT->getReturnType()));
// Output the number of arguments to function (+1 if varargs):
- output_vbr((unsigned)MT->getNumParams()+MT->isVarArg());
+ output_vbr((unsigned)FT->getNumParams()+FT->isVarArg());
// Output all of the arguments...
- FunctionType::param_iterator I = MT->param_begin();
- unsigned Idx = 1;
- for (; I != MT->param_end(); ++I) {
- Slot = Table.getSlot(*I);
- assert(Slot != -1 && "Type used but not available!!");
- output_typeid((unsigned)Slot);
- output_vbr(unsigned(MT->getParamAttrs(Idx)));
- Idx++;
- }
+ FunctionType::param_iterator I = FT->param_begin();
+ for (; I != FT->param_end(); ++I)
+ output_typeid(Table.getTypeSlot(*I));
// Terminate list with VoidTy if we are a varargs function...
- if (MT->isVarArg())
+ if (FT->isVarArg())
output_typeid((unsigned)Type::VoidTyID);
+
+ // Put out all the parameter attributes
+ outputParamAttrsList(FT->getParamAttrs());
break;
}
case Type::ArrayTyID: {
const ArrayType *AT = cast<ArrayType>(T);
- int Slot = Table.getSlot(AT->getElementType());
- assert(Slot != -1 && "Type used but not available!!");
- output_typeid((unsigned)Slot);
+ output_typeid(Table.getTypeSlot(AT->getElementType()));
output_vbr(AT->getNumElements());
break;
}
- case Type::PackedTyID: {
- const PackedType *PT = cast<PackedType>(T);
- int Slot = Table.getSlot(PT->getElementType());
- assert(Slot != -1 && "Type used but not available!!");
- output_typeid((unsigned)Slot);
+ case Type::VectorTyID: {
+ const VectorType *PT = cast<VectorType>(T);
+ output_typeid(Table.getTypeSlot(PT->getElementType()));
output_vbr(PT->getNumElements());
break;
}
// Output all of the element types...
for (StructType::element_iterator I = ST->element_begin(),
E = ST->element_end(); I != E; ++I) {
- int Slot = Table.getSlot(*I);
- assert(Slot != -1 && "Type used but not available!!");
- output_typeid((unsigned)Slot);
+ output_typeid(Table.getTypeSlot(*I));
}
// Terminate list with VoidTy
break;
}
- case Type::PointerTyID: {
- const PointerType *PT = cast<PointerType>(T);
- int Slot = Table.getSlot(PT->getElementType());
- assert(Slot != -1 && "Type used but not available!!");
- output_typeid((unsigned)Slot);
+ case Type::PointerTyID:
+ output_typeid(Table.getTypeSlot(cast<PointerType>(T)->getElementType()));
break;
- }
case Type::OpaqueTyID:
// No need to emit anything, just the count of opaque types is enough.
output_vbr(CE->getOpcode()); // Put out the CE op code
for (User::const_op_iterator OI = CE->op_begin(); OI != CE->op_end(); ++OI){
- int Slot = Table.getSlot(*OI);
- assert(Slot != -1 && "Unknown constant used in ConstantExpr!!");
- output_vbr((unsigned)Slot);
- Slot = Table.getSlot((*OI)->getType());
- output_typeid((unsigned)Slot);
+ output_vbr(Table.getSlot(*OI));
+ output_typeid(Table.getTypeSlot((*OI)->getType()));
}
if (CE->isCompare())
output_vbr((unsigned)CE->getPredicate());
switch (CPV->getType()->getTypeID()) {
case Type::IntegerTyID: { // Integer types...
+ const ConstantInt *CI = cast<ConstantInt>(CPV);
unsigned NumBits = cast<IntegerType>(CPV->getType())->getBitWidth();
if (NumBits <= 32)
- output_vbr(uint32_t(cast<ConstantInt>(CPV)->getZExtValue()));
+ output_vbr(uint32_t(CI->getZExtValue()));
else if (NumBits <= 64)
- output_vbr(uint64_t(cast<ConstantInt>(CPV)->getZExtValue()));
- else
- assert("Integer types > 64 bits not supported.");
+ output_vbr(uint64_t(CI->getZExtValue()));
+ else {
+ // We have an arbitrary precision integer value to write whose
+ // bit width is > 64. However, in canonical unsigned integer
+ // format it is likely that the high bits are going to be zero.
+ // So, we only write the number of active words.
+ uint32_t activeWords = CI->getValue().getActiveWords();
+ const uint64_t *rawData = CI->getValue().getRawData();
+ output_vbr(activeWords);
+ for (uint32_t i = 0; i < activeWords; ++i)
+ output_vbr(rawData[i]);
+ }
break;
}
const ConstantArray *CPA = cast<ConstantArray>(CPV);
assert(!CPA->isString() && "Constant strings should be handled specially!");
- for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) {
- int Slot = Table.getSlot(CPA->getOperand(i));
- assert(Slot != -1 && "Constant used but not available!!");
- output_vbr((unsigned)Slot);
- }
+ for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i)
+ output_vbr(Table.getSlot(CPA->getOperand(i)));
break;
}
- case Type::PackedTyID: {
- const ConstantPacked *CP = cast<ConstantPacked>(CPV);
-
- for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
- int Slot = Table.getSlot(CP->getOperand(i));
- assert(Slot != -1 && "Constant used but not available!!");
- output_vbr((unsigned)Slot);
- }
+ case Type::VectorTyID: {
+ const ConstantVector *CP = cast<ConstantVector>(CPV);
+ for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
+ output_vbr(Table.getSlot(CP->getOperand(i)));
break;
}
case Type::StructTyID: {
const ConstantStruct *CPS = cast<ConstantStruct>(CPV);
- for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) {
- int Slot = Table.getSlot(CPS->getOperand(i));
- assert(Slot != -1 && "Constant used but not available!!");
- output_vbr((unsigned)Slot);
- }
+ for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i)
+ output_vbr(Table.getSlot(CPS->getOperand(i)));
break;
}
// Emit all of the strings.
for (I = Table.string_begin(); I != E; ++I) {
const ConstantArray *Str = *I;
- int Slot = Table.getSlot(Str->getType());
- assert(Slot != -1 && "Constant string of unknown type?");
- output_typeid((unsigned)Slot);
+ output_typeid(Table.getTypeSlot(Str->getType()));
// Now that we emitted the type (which indicates the size of the string),
// emit all of the characters.
output_typeid(Type); // Result type
unsigned NumArgs = I->getNumOperands();
- output_vbr(NumArgs + (isa<CastInst>(I) || isa<InvokeInst>(I) ||
- isa<CmpInst>(I) || isa<VAArgInst>(I) || Opcode == 58));
+ bool HasExtraArg = false;
+ if (isa<CastInst>(I) || isa<InvokeInst>(I) ||
+ isa<CmpInst>(I) || isa<VAArgInst>(I) || Opcode == 58 ||
+ Opcode == 62 || Opcode == 63)
+ HasExtraArg = true;
+ if (const AllocationInst *AI = dyn_cast<AllocationInst>(I))
+ HasExtraArg = AI->getAlignment() != 0;
+
+ output_vbr(NumArgs + HasExtraArg);
if (!isa<GetElementPtrInst>(&I)) {
- for (unsigned i = 0; i < NumArgs; ++i) {
- int Slot = Table.getSlot(I->getOperand(i));
- assert(Slot >= 0 && "No slot number for value!?!?");
- output_vbr((unsigned)Slot);
- }
+ for (unsigned i = 0; i < NumArgs; ++i)
+ output_vbr(Table.getSlot(I->getOperand(i)));
if (isa<CastInst>(I) || isa<VAArgInst>(I)) {
- int Slot = Table.getSlot(I->getType());
- assert(Slot != -1 && "Cast return type unknown?");
- output_typeid((unsigned)Slot);
+ output_typeid(Table.getTypeSlot(I->getType()));
} else if (isa<CmpInst>(I)) {
output_vbr(unsigned(cast<CmpInst>(I)->getPredicate()));
} else if (isa<InvokeInst>(I)) {
} else if (Opcode == 58) { // Call escape sequence
output_vbr((cast<CallInst>(I)->getCallingConv() << 1) |
unsigned(cast<CallInst>(I)->isTailCall()));
+ } else if (const AllocationInst *AI = dyn_cast<AllocationInst>(I)) {
+ if (AI->getAlignment())
+ output_vbr((unsigned)Log2_32(AI->getAlignment())+1);
+ } else if (Opcode == 62) { // Attributed load
+ output_vbr((unsigned)(((Log2_32(cast<LoadInst>(I)->getAlignment())+1)<<1)
+ + (cast<LoadInst>(I)->isVolatile() ? 1 : 0)));
+ } else if (Opcode == 63) { // Attributed store
+ output_vbr((unsigned)(((Log2_32(cast<StoreInst>(I)->getAlignment())+1)<<1)
+ + (cast<StoreInst>(I)->isVolatile() ? 1 : 0)));
}
} else {
- int Slot = Table.getSlot(I->getOperand(0));
- assert(Slot >= 0 && "No slot number for value!?!?");
- output_vbr(unsigned(Slot));
+ output_vbr(Table.getSlot(I->getOperand(0)));
// We need to encode the type of sequential type indices into their slot #
unsigned Idx = 1;
for (gep_type_iterator TI = gep_type_begin(I), E = gep_type_end(I);
Idx != NumArgs; ++TI, ++Idx) {
- Slot = Table.getSlot(I->getOperand(Idx));
- assert(Slot >= 0 && "No slot number for value!?!?");
+ unsigned Slot = Table.getSlot(I->getOperand(Idx));
if (isa<SequentialType>(*TI)) {
// These should be either 32-bits or 64-bits, however, with bit
unsigned IdxId = BitWidth == 32 ? 0 : 1;
Slot = (Slot << 1) | IdxId;
}
- output_vbr(unsigned(Slot));
+ output_vbr(Slot);
}
}
}
// The type for the function has already been emitted in the type field of the
// instruction. Just emit the slot # now.
- 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);
- }
+ for (unsigned i = 0; i != NumFixedOperands; ++i)
+ output_vbr(Table.getSlot(I->getOperand(i)));
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_typeid((unsigned)Slot);
+ output_typeid(Table.getTypeSlot(I->getOperand(i)->getType()));
// Output arg ID itself
- Slot = Table.getSlot(I->getOperand(i));
- assert(Slot >= 0 && "No slot number for value!?!?");
- output_vbr((unsigned)Slot);
+ output_vbr(Table.getSlot(I->getOperand(i)));
}
if (isa<InvokeInst>(I)) {
unsigned Opcode = I.getOpcode();
unsigned NumOperands = I.getNumOperands();
- // Encode 'tail call' as 61, 'volatile load' as 62, and 'volatile store' as
+ // Encode 'tail call' as 61
// 63.
if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
if (CI->getCallingConv() == CallingConv::C) {
} else {
Opcode = 58; // Call escape sequence.
}
- } else if (isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) {
- Opcode = 62;
- } else if (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) {
- Opcode = 63;
}
// Figure out which type to encode with the instruction. Typically we want
break;
}
- unsigned Type;
- int Slot = Table.getSlot(Ty);
- assert(Slot != -1 && "Type not available!!?!");
- Type = (unsigned)Slot;
+ unsigned Type = Table.getTypeSlot(Ty);
// Varargs calls and invokes are encoded entirely different from any other
// instructions.
unsigned Slots[3]; Slots[0] = (1 << 12)-1; // Marker to signify 0 operands
for (unsigned i = 0; i != NumOperands; ++i) {
- int slot = Table.getSlot(I.getOperand(i));
- assert(slot != -1 && "Broken bytecode!");
- if (unsigned(slot) > MaxOpSlot) MaxOpSlot = unsigned(slot);
- Slots[i] = unsigned(slot);
+ unsigned Slot = Table.getSlot(I.getOperand(i));
+ if (Slot > MaxOpSlot) MaxOpSlot = Slot;
+ Slots[i] = Slot;
}
// Handle the special cases for various instructions...
if (isa<CastInst>(I) || isa<VAArgInst>(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] != ~0U && "Cast return type unknown?");
+ Slots[1] = Table.getTypeSlot(I.getType());
if (Slots[1] > MaxOpSlot) MaxOpSlot = Slots[1];
NumOperands++;
} else if (const AllocationInst *AI = dyn_cast<AllocationInst>(&I)) {
} else if (isa<InvokeInst>(I)) {
// Invoke escape seq has at least 4 operands to encode.
++NumOperands;
+ } else if (const LoadInst *LI = dyn_cast<LoadInst>(&I)) {
+ // Encode attributed load as opcode 62
+ // We need to encode the attributes of the load instruction as the second
+ // operand. Its not really a slot, but we don't want to break the
+ // instruction format for these instructions.
+ if (LI->getAlignment() || LI->isVolatile()) {
+ NumOperands = 2;
+ Slots[1] = ((Log2_32(LI->getAlignment())+1)<<1) +
+ (LI->isVolatile() ? 1 : 0);
+ if (Slots[1] > MaxOpSlot)
+ MaxOpSlot = Slots[1];
+ Opcode = 62;
+ }
+ } else if (const StoreInst *SI = dyn_cast<StoreInst>(&I)) {
+ // Encode attributed store as opcode 63
+ // We need to encode the attributes of the store instruction as the third
+ // operand. Its not really a slot, but we don't want to break the
+ // instruction format for these instructions.
+ if (SI->getAlignment() || SI->isVolatile()) {
+ NumOperands = 3;
+ Slots[2] = ((Log2_32(SI->getAlignment())+1)<<1) +
+ (SI->isVolatile() ? 1 : 0);
+ if (Slots[2] > MaxOpSlot)
+ MaxOpSlot = Slots[2];
+ Opcode = 63;
+ }
}
// Decide which instruction encoding to use. This is determined primarily
outputModuleInfoBlock(M);
// Output module level constants, used for global variable initializers
- outputConstants(false);
+ outputConstants();
// Do the whole module now! Process each function at a time...
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
// Helper function for outputConstants().
// Writes out all the constants in the plane Plane starting at entry StartNo.
//
-void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
- &Plane, unsigned StartNo) {
+void BytecodeWriter::outputConstantsInPlane(const Value *const *Plane,
+ unsigned PlaneSize,
+ unsigned StartNo) {
unsigned ValNo = StartNo;
// Scan through and ignore function arguments, global values, and constant
// strings.
- for (; ValNo < Plane.size() &&
+ for (; ValNo < PlaneSize &&
(isa<Argument>(Plane[ValNo]) || isa<GlobalValue>(Plane[ValNo]) ||
(isa<ConstantArray>(Plane[ValNo]) &&
cast<ConstantArray>(Plane[ValNo])->isString())); ValNo++)
/*empty*/;
unsigned NC = ValNo; // Number of constants
- for (; NC < Plane.size() && (isa<Constant>(Plane[NC]) ||
- isa<InlineAsm>(Plane[NC])); NC++)
+ for (; NC < PlaneSize && (isa<Constant>(Plane[NC]) ||
+ isa<InlineAsm>(Plane[NC])); NC++)
/*empty*/;
NC -= ValNo; // Convert from index into count
if (NC == 0) return; // Skip empty type planes...
//
output_vbr(NC);
- // Put out the Type ID Number...
- int Slot = Table.getSlot(Plane.front()->getType());
- assert (Slot != -1 && "Type in constant pool but not in function!!");
- output_typeid((unsigned)Slot);
+ // Put out the Type ID Number.
+ output_typeid(Table.getTypeSlot(Plane[0]->getType()));
for (unsigned i = ValNo; i < ValNo+NC; ++i) {
const Value *V = Plane[i];
return Ty != Type::LabelTy && Ty != Type::VoidTy && !isa<OpaqueType>(Ty);
}
-void BytecodeWriter::outputConstants(bool isFunction) {
+void BytecodeWriter::outputConstants() {
BytecodeBlock CPool(BytecodeFormat::ConstantPoolBlockID, *this,
true /* Elide block if empty */);
unsigned NumPlanes = Table.getNumPlanes();
- if (isFunction)
- // Output the type plane before any constants!
- outputTypes(Table.getModuleTypeLevel());
- else
- // Output module-level string constants before any other constants.
- outputConstantStrings();
+ // Output module-level string constants before any other constants.
+ outputConstantStrings();
for (unsigned pno = 0; pno != NumPlanes; pno++) {
- const std::vector<const Value*> &Plane = Table.getPlane(pno);
+ const SlotCalculator::TypePlane &Plane = Table.getPlane(pno);
if (!Plane.empty()) { // Skip empty type planes...
unsigned ValNo = 0;
- if (isFunction) // Don't re-emit module constants
- ValNo += Table.getModuleLevel(pno);
-
if (hasNullValue(Plane[0]->getType())) {
// Skip zero initializer
- if (ValNo == 0)
- ValNo = 1;
+ ValNo = 1;
}
// Write out constants in the plane
- outputConstantsInPlane(Plane, ValNo);
+ outputConstantsInPlane(&Plane[0], Plane.size(), ValNo);
}
}
}
// 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) {
- int Slot = Table.getSlot(I->getType());
- assert(Slot != -1 && "Module global vars is broken!");
+ unsigned Slot = Table.getTypeSlot(I->getType());
assert((I->hasInitializer() || !I->hasInternalLinkage()) &&
"Global must have an initializer or have external linkage!");
// Fields: bit0 = isConstant, bit1 = hasInitializer, bit2-4=Linkage,
- // bit5+ = Slot # for type.
+ // bit5 = isThreadLocal, bit6+ = Slot # for type.
bool HasExtensionWord = (I->getAlignment() != 0) ||
I->hasSection() ||
(I->getVisibility() != GlobalValue::DefaultVisibility);
// If we need to use the extension byte, set linkage=3(internal) and
// initializer = 0 (impossible!).
if (!HasExtensionWord) {
- unsigned oSlot = ((unsigned)Slot << 5) | (getEncodedLinkage(I) << 2) |
- (I->hasInitializer() << 1) | (unsigned)I->isConstant();
+ unsigned oSlot = (Slot << 6)| (((unsigned)I->isThreadLocal()) << 5) |
+ (getEncodedLinkage(I) << 2) | (I->hasInitializer() << 1)
+ | (unsigned)I->isConstant();
output_vbr(oSlot);
} else {
- unsigned oSlot = ((unsigned)Slot << 5) | (3 << 2) |
- (0 << 1) | (unsigned)I->isConstant();
+ unsigned oSlot = (Slot << 6) | (((unsigned)I->isThreadLocal()) << 5) |
+ (3 << 2) | (0 << 1) | (unsigned)I->isConstant();
output_vbr(oSlot);
// The extension word has this format: bit 0 = has initializer, bit 1-3 =
}
// If we have an initializer, output it now.
- if (I->hasInitializer()) {
- Slot = Table.getSlot((Value*)I->getInitializer());
- assert(Slot != -1 && "No slot for global var initializer!");
- output_vbr((unsigned)Slot);
- }
+ if (I->hasInitializer())
+ output_vbr(Table.getSlot((Value*)I->getInitializer()));
}
- output_typeid((unsigned)Table.getSlot(Type::VoidTy));
+ output_typeid(Table.getTypeSlot(Type::VoidTy));
// Output the types of the functions in this module.
for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
- int Slot = Table.getSlot(I->getType());
- assert(Slot != -1 && "Module slot calculator is broken!");
- assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
+ unsigned Slot = Table.getTypeSlot(I->getType());
assert(((Slot << 6) >> 6) == Slot && "Slot # too big!");
unsigned CC = I->getCallingConv()+1;
unsigned ID = (Slot << 5) | (CC & 15);
- if (I->isExternal()) // If external, we don't have an FunctionInfo block.
+ if (I->isDeclaration()) // If external, we don't have an FunctionInfo block.
ID |= 1 << 4;
if (I->getAlignment() || I->hasSection() || (CC & ~15) != 0 ||
- (I->isExternal() && I->hasDLLImportLinkage()) ||
- (I->isExternal() && I->hasExternalWeakLinkage())
+ (I->isDeclaration() && I->hasDLLImportLinkage()) ||
+ (I->isDeclaration() && I->hasExternalWeakLinkage())
)
ID |= 1 << 31; // Do we need an extension word?
// convention, bit 10 = hasSectionID., bits 11-12 = external linkage type
unsigned extLinkage = 0;
- if (I->isExternal()) {
+ if (I->isDeclaration()) {
if (I->hasDLLImportLinkage()) {
extLinkage = 1;
} else if (I->hasExternalWeakLinkage()) {
}
}
}
- output_vbr((unsigned)Table.getSlot(Type::VoidTy) << 5);
+ output_vbr(Table.getTypeSlot(Type::VoidTy) << 5);
// Emit the list of dependent libraries for the Module.
Module::lib_iterator LI = M->lib_begin();
void BytecodeWriter::outputFunction(const Function *F) {
// If this is an external function, there is nothing else to emit!
- if (F->isExternal()) return;
+ if (F->isDeclaration()) return;
BytecodeBlock FunctionBlock(BytecodeFormat::FunctionBlockID, *this);
unsigned rWord = (getEncodedVisibility(F) << 16) | getEncodedLinkage(F);
// Get slot information about the function...
Table.incorporateFunction(F);
- outputConstants(true);
-
// Output all of the instructions in the body of the function
outputInstructions(F);
for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
TI != TE; ++TI) {
// Symtab entry:[def slot #][name]
- output_typeid((unsigned)Table.getSlot(TI->second));
+ output_typeid(Table.getTypeSlot(TI->second));
output(TI->first);
}
}
-void BytecodeWriter::outputValueSymbolTable(const SymbolTable &MST) {
+void BytecodeWriter::outputValueSymbolTable(const ValueSymbolTable &VST) {
// Do not output the Bytecode block for an empty symbol table, it just wastes
// space!
- if (MST.isEmpty()) return;
+ if (VST.empty()) return;
BytecodeBlock SymTabBlock(BytecodeFormat::ValueSymbolTableBlockID, *this,
true/*ElideIfEmpty*/);
- // Now do each of the type planes in order.
- for (SymbolTable::plane_const_iterator PI = MST.plane_begin(),
- PE = MST.plane_end(); PI != PE; ++PI) {
- SymbolTable::value_const_iterator I = MST.value_begin(PI->first);
- SymbolTable::value_const_iterator End = MST.value_end(PI->first);
- int Slot;
+ // Organize the symbol table by type
+ typedef SmallVector<const ValueName*, 8> PlaneMapVector;
+ typedef DenseMap<const Type*, PlaneMapVector> PlaneMap;
+ PlaneMap Planes;
+ for (ValueSymbolTable::const_iterator SI = VST.begin(), SE = VST.end();
+ SI != SE; ++SI)
+ Planes[SI->getValue()->getType()].push_back(&*SI);
+
+ for (PlaneMap::iterator PI = Planes.begin(), PE = Planes.end();
+ PI != PE; ++PI) {
+ PlaneMapVector::const_iterator I = PI->second.begin();
+ PlaneMapVector::const_iterator End = PI->second.end();
if (I == End) continue; // Don't mess with an absent type...
output_vbr((unsigned)PI->second.size());
// Write the slot number of the type for this plane
- Slot = Table.getSlot(PI->first);
- assert(Slot != -1 && "Type in symtab, but not in table!");
- output_typeid((unsigned)Slot);
+ output_typeid(Table.getTypeSlot(PI->first));
// Write each of the values in this plane
for (; I != End; ++I) {
// Symtab entry: [def slot #][name]
- Slot = Table.getSlot(I->second);
- assert(Slot != -1 && "Value in symtab but has no slot number!!");
- output_vbr((unsigned)Slot);
- output(I->first);
+ output_vbr(Table.getSlot((*I)->getValue()));
+ output_str((*I)->getKeyData(), (*I)->getKeyLength());
}
}
}