//
//===----------------------------------------------------------------------===//
-#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/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>
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);
- output_typeid(Table.getTypeSlot(MT->getReturnType()));
- 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) {
+ FunctionType::param_iterator I = FT->param_begin();
+ for (; I != FT->param_end(); ++I)
output_typeid(Table.getTypeSlot(*I));
- output_vbr(unsigned(MT->getParamAttrs(Idx)));
- Idx++;
- }
// 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;
}
break;
}
- case Type::PackedTyID: {
- const PackedType *PT = cast<PackedType>(T);
+ case Type::VectorTyID: {
+ const VectorType *PT = cast<VectorType>(T);
output_typeid(Table.getTypeSlot(PT->getElementType()));
output_vbr(PT->getNumElements());
break;
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;
}
break;
}
- case Type::PackedTyID: {
- const ConstantPacked *CP = cast<ConstantPacked>(CPV);
+ 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;
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)
} 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 {
output_vbr(Table.getSlot(I->getOperand(0)));
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
} 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
// 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.
- output_typeid(Table.getTypeSlot(Plane.front()->getType()));
+ output_typeid(Table.getTypeSlot(Plane[0]->getType()));
for (unsigned i = ValNo; i < ValNo+NC; ++i) {
const Value *V = Plane[i];
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 (hasNullValue(Plane[0]->getType())) {
}
// Write out constants in the plane
- outputConstantsInPlane(Plane, ValNo);
+ outputConstantsInPlane(&Plane[0], Plane.size(), ValNo);
}
}
}
"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 = (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 = (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 =
unsigned CC = I->getCallingConv()+1;
unsigned ID = (Slot << 5) | (CC & 15);
- if (I->isDeclaration()) // 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 ||
true/*ElideIfEmpty*/);
// Organize the symbol table by type
- typedef std::pair<const std::string*, const Value*> PlaneMapEntry;
- typedef std::vector<PlaneMapEntry> PlaneMapVector;
- typedef std::map<const Type*, PlaneMapVector > PlaneMap;
+ 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->second->getType()]
- .push_back(std::make_pair(&SI->first, SI->second));
+ Planes[SI->getValue()->getType()].push_back(&*SI);
- for (PlaneMap::const_iterator PI = Planes.begin(), PE = Planes.end();
+ 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();
// Write each of the values in this plane
for (; I != End; ++I) {
// Symtab entry: [def slot #][name]
- output_vbr(Table.getSlot(I->second));
- output(*I->first);
+ output_vbr(Table.getSlot((*I)->getValue()));
+ output_str((*I)->getKeyData(), (*I)->getKeyLength());
}
}
}